home *** CD-ROM | disk | FTP | other *** search
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
-
- #include "mselect.h" /*external selection of microprocessor symbol table*/
- #include "proto.h"
- #include "as.h"
- #include "extvars.h"
- #include "structs.h"
-
-
- /*
- * 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(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(void)
- { /* get another line and find token in it *//* s
- * imilar to make_pass() except one line at a
- * time */
- /* most variables & constants are global */
-
- /* struct nlist *lookup(); */
-
- if (FGETS(Line, MAXBUF - 1, Fd) == (char *) NULL)
- 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(void)
- {
- 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(void)
- {
- 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 */
- }
-