OpenCores
URL https://opencores.org/ocsvn/System09/System09/trunk

Subversion Repositories System09

[/] [System09/] [trunk/] [Tools/] [as09/] [ifd.c] - Rev 137

Go to most recent revision | Compare with Previous | Blame | View Log

/* IfMachine() --- This function implements the IFD & IFND conditional
                assembly machine.
                version 1.0 made for release TER_2.0 cross assembler 27 Jun 89
*/
 
#define FALSE_BLOCK     0       /* values for state variable */
#define TRUE_BLOCK      1
#define POP_TEST        2
#define ELSE_TEST       3
#define FALSE           0
#define TRUE            1
 
void IfMachine(Token)
int Token;      /* input token from calling machine */
                /* See file as.h for definition (globals) */
{
  static int State = TRUE_BLOCK, StackPt = 0, IfStack[MAXIFD];
                /* State variable, pointer to "IF stack pointer" and "Stack" */
  int Hiatus;   /* flag to break out of FSM & resume normal processing */
 
  Hiatus=FALSE; /* infinite loop to operate machine
                                 until time to break out */
  do    /* test at end */
   {
 
#ifdef DEBUG3
  printf("IfMachine state=%u , token=%u\n",State,Token);
#endif
 
   if (State == TRUE_BLOCK)     /* a block of statements processed normally */
     switch(Token) {
        case IF_TRUE:
                IfStack[StackPt]=TRUE;
                if (++StackPt > MAXIFD) {       /* check for over flow */
                        StackPt = MAXIFD;
                        error("Error:IFD/IFND nested too deep");
                        }
                /* print_line() will be done in normal processing */
                Hiatus = TRUE;  /* resume normal line processing */
                break;
        case IF_FALSE:
                IfStack[StackPt]=TRUE;
                if (++StackPt > MAXIFD) {       /* check for over flow */
                        StackPt = MAXIFD;
                        error("Error:IFD/IFND nested too deep");
                        }
                if (Pass == 2 && Lflag && !N_page)      /* need to print here */
                        print_line(); /* cuz will not return to normal */
                Token = GetToken(); /* get next line & examine for IF */
                State = FALSE_BLOCK; /* change state */
                break;
        case IF_ELSE:
                if (StackPt == 0) /* bad IF nesting */
                        error("Error: ELSE without IF");
                if (Pass == 2 && Lflag && !N_page)
                        print_line();
                Token = GetToken(); /* get next line & examine for IF */
                State = FALSE_BLOCK;
                break;
        case IF_ENDIF:
                if (StackPt == 0)       /* bad IF nesting */
                        error("Error: ENDIF without IF");
                else
                        StackPt--; /* popped state must be TRUE */
                 Hiatus = TRUE;
                 break;
        /* case NORMAL is not implemented as it represents normal line
                processing. */
        case IF_END:    /* file ended with improperly nested IFD */
                        /* this code can't actually be reached at present
                           in a TRUE_BLOCK */
                fatal("Error: file ended before IFD/IFND/ELSE/ENDIF");
                break;
        default:        /* This code can't be reached at the present.
                           Logically would happen if EOF but handled
                           else where */
                fatal("Can't get here from there.");
                break;
      }
   else if (State == FALSE_BLOCK)       /* statements not processed */
     switch(Token) {
        case IF_TRUE:   /* doesn't make any diff. Just nest IFs */
        case IF_FALSE:
                IfStack[StackPt]=FALSE;
                if (++StackPt > MAXIFD) {
                        StackPt = MAXIFD;
                        error("Error:IFD/IFND nested too deep");
                        }
                if (Pass == 2 && Lflag && !N_page)
                        print_line();
                Token = GetToken();
                break;
        case IF_ELSE:
             /* if (Pass == 2 && Lflag && !N_page) */
             /*         print_line();              */
                State = ELSE_TEST;
                break;
        case IF_ENDIF:
                State = POP_TEST;
                break;
        case IF_END:    /* file ended with improperly nested IFD */
                fatal("Fatal Error: file ended before last ENDIF");
                        /* Fatal will exit assembler.  Things are too
                           messed up.  Include file handling is else where
                           and don't want to duplicate here. */
                break;
        case IF_NORMAL: /* normal line in a FALSE BLOCK */
                if (Pass == 2 && Lflag && !N_page)
                        print_line();
                Token = GetToken();
                break;
        default:
                fatal("Fatal Error: file ended before last ENDIF");
                        /* must be EOF or something else terrible */
                break;
     }
   else if (State == POP_TEST) {        /* pop up outside nest state */
     if (StackPt == 0) {        /* bad IF nesting */
        error("Error: ENDIF without IF");
        if (Pass == 2 && Lflag && !N_page)
                        print_line();
        State = TRUE;
        }
     else {
        StackPt--;      /* pop stack */
        if (IfStack[StackPt] == TRUE) { /* back to normal */
                /* had to come from FALSE block cuz TRUE block cannot
                        be inside FALSE block */
                if (Pass == 2 && Lflag && !N_page)
                        print_line();
                State = TRUE;
                Hiatus = TRUE;  /* sleep for normal line processing */
                }
        else {  /* gotta be that stack == FALSE, still inside FALSE nest */
                if (Pass == 2 && Lflag && !N_page)
                        print_line();
                State = FALSE;
                Token = GetToken();
                }
          }
     }
   else if (State == ELSE_TEST) {       /* change state */
        if (IfStack[StackPt-1] == TRUE) {
                State = TRUE_BLOCK;
                Hiatus = TRUE;
                }
        else
                State = FALSE_BLOCK;
      }
   }
while (Hiatus == FALSE);        /* loop if not exit */
}
 
 
/* GetToken() --- get another line from within False Block and extract token
                as would be done in pseudo.c.  Returns token id:
                        IF_TRUE         IFD/IFND evaluated to TRUE
                        IF_FALSE        IFD/IFND evaluated to FALSE
                        IF_ELSE         ELSE pseudo op
                        IF_ENDIF        ENDIF pseudo op
                        IF_END          END pseudo op
                        IF_NORMAL       none of the above, perhaps assy code
                        IF_EOF          encountered end of file
                This function exists because conditional assembly was added
                as pseudo op rather than with key character ("%") and did
                not want to disturb original software topology */
 
int GetToken()  /* get another line and find token in it */
{               /* similar to make_pass() except one line at a time */
                /* most variables & constants are global */
 
#ifndef IBM
  if (FGETS(Line,MAXBUF-1,Fd) == (char *)NULL)
#else
  if (fgets(Line,MAXBUF,Fd) == (char *)NULL)
#endif
        return(IF_EOF); /* banged into eof */
  Line_num++;
  P_force=0;
  N_page=0;
  if (!parse_line())
        return(IF_NORMAL);      /* comment line */
  if (*Op==EOS)                 /* skipping over label, probably. */
        return(IF_NORMAL);      /* strcmp() returns 0 if arg1 is NULL string */
 
  if (strcmp(Op,"ifd")==0)
        return(eval_ifd());
  else if (strcmp(Op,"ifnd")==0)
        return(eval_ifnd());
  else if (strcmp(Op,"else")==0)
        return(IF_ELSE);
  else if (strcmp(Op,"endif")==0)
        return(IF_ENDIF);
  else if (strcmp(Op,"end")==0)
        return(IF_END);
  else
        return(IF_NORMAL);      /* or might be garbage...but who cares?
                                   This is FALSE BLOCK */
}
 
 
/*
*  eval_ifd() --- evaluate an if define statement for TRUE or FALSE
*/
 
int
eval_ifd()
         {
  struct nlist *np;     /* symbol structure */
 
        if (*Operand==EOS) {
                warn("No symbol for IFD");
                return(IF_FALSE);       /* nothing to check */
                }
        if ((np=lookup(Operand)) == NULL)
                return(IF_FALSE);       /* not defined at all...yet */
        else
                if(np->def2 == Pass)
                        return(IF_TRUE); /* defined for this pass */
 
        return(IF_FALSE);       /* not defined this pass */
        }
 
/*
*  eval_ifnd() --- evaluate an if not define statement for TRUE or FALSE
*/
 
int
eval_ifnd()
 {
  struct nlist *np;     /* symbol structure */
 
        if (*Operand==EOS) {
                warn("No symbol for IFND");
                return(IF_TRUE);        /* nothing to check */
                }
        if ((np=lookup(Operand)) == NULL)
                return(IF_TRUE);        /* not defined at all...yet */
        else
                if(np->def2 == Pass)
                        return(IF_FALSE); /* defined for this pass */
 
        return(IF_TRUE);        /* not defined this pass */
 }
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.