/*------------------------------------------------------------------*/ /* */ /* MC68000 Cross Assembler */ /* */ /* Copyright (c) 1985 by Brian R. Anderson */ /* */ /* Symbol table manipulation - September 9, 1987 */ /* */ /* This program may be copied for personal, non-commercial use */ /* only, provided that the above copyright notice is included */ /* on all copies of the source code. Copying for any other use */ /* without the consent of the author is prohibited. */ /* */ /*------------------------------------------------------------------*/ /* */ /* Originally published (in Modula-2) in */ /* Dr. Dobb's Journal, April, May, and June 1986. */ /* */ /* AmigaDOS conversion copyright (c) 1987 by Charlie Gibbs. */ /* */ /*------------------------------------------------------------------*/ #include #include "a68kdef.h" #include "a68kglb.h" long Value; /* Passed from ReadSymTab to CalcValue */ /* Functions */ extern int Instructions(), ObjDir(); extern int GetInstModeSize(), GetMultReg(); extern int GetArgs(), GetAReg(); extern long AddrBndW(), AddrBndL(); extern char *malloc(); extern FILE *fopen(); int LineParts(), GetField(), ReadSymTab(), GetSize(), OpenIncl(); long GetValue(), CalcValue(); int OpenIncl (name, dirlist) char name[], dirlist[]; /* Opens the file whose name is in "name". The current directory is tried first. If that fails, the directory names in "dirlist" (separated by commas) are then tried until either a file is found or the list is exhausted. If the file is found in a subdirectory, "name" is modified to include the entire path specification. If another input file is open when this routine is called, it is closed first. Returns TRUE if successful, FALSE if not. */ { register int i; char dirname[MAXLINE]; if (InFile != NULL) fclose (InFile); /* Close the inner file */ if ((InFile = fopen (name, "r")) != NULL) return (TRUE); /* Found it in current directory */ i = 0; while (dirlist[i] != '\0') { i = GetField (dirlist, i, dirname); if ((dirname[i-1] != '/') && (dirname[i-1] != ':')) strcat (dirname, "/"); /* Slash after directory name */ strcat (dirname, name); if ((InFile = fopen (dirname, "r")) != NULL) { strcpy (name, dirname); /* Return entire path */ return (TRUE); /* Found it in a subdirectory */ } if (dirlist[i] != '\0') i++; /* Skip over separator and try again */ } return (FALSE); /* Couldn't find it anywhere */ } int LineParts (dummy) int dummy; /* Gets the next statement and extracts its component parts. If end of file is reached, and we're in a macro or include file, the file is closed and the next outermost file is continued. If we have reached the end of the source file, or encounter an ENDM or MEXIT directive, the current input file closed and TRUE is returned. If we're in a user macro (indicated by UPtr being nonzero), we'll get the next statement from the save area in memory instead. Macro arguments, if any, are substituted. LineCount is incremented if a statement was successfully read. If this is the first call of this routine (i.e. LineCount is zero) and HeaderFN is not a null string, we'll return an INCLUDE statement requesting the specified header file, rather than reading the first statement from the source file. The following fields are set up: Line - statement line image Label - instruction label (without trailing colon) OpCode - instruction mnemonic (converted to upper case) SrcOp - first (source) operand DestOp - second (destination) operand Size - size from OpCode SrcLoc - displacement to start of source operand DestLoc - displacement to start of destination operand InFNum - decremented if end of file is reached InF - incremented if end of file is reached LabLine - set to LineCount if this line is labeled (unless it's a local label) */ { register int i, j, c; register char *argptr; char subline[MAXLINE]; while (1) { /* Repeat until we get something (not end of INCLUDE) */ Line[0] = Label[0] = OpCode[0] = SrcOp[0] = DestOp[0] = '\0'; OpLoc = SrcLoc = DestLoc = 0; if ((LineCount==0) && (HeaderFN[0])) { /* Header file */ strcpy (Line, " INCLUDE "); /* Make an INCLUDE stmt. */ strcat (Line, HeaderFN); strcat (Line, " ;Generated for header file"); strcpy (OpCode, "INCLUDE"); /* Dummy op code */ OpLoc = 8; strcpy (SrcOp, HeaderFN); /* Dummy source operand */ SrcLoc = 16; LineCount++; errlim = AddrAdv = InstSize = nO = nS = nD = nX = 0; PrntAddr = FALSE; return (FALSE); } if (InF->UPtr != 0) { /* User macro input */ strcpy (Line, InF->UPtr); InF->UPtr += strlen (Line) + 1; c = '\n'; } else { /* Normal file input */ i = 0; while ((c=getc(InFile)) != '\n') { /* Get Line, expanding tabs */ if (c == 26) c = EOF; /* Catch MS-DOS EOF char. */ if (c == EOF) { if (i > 0) { /* Last line has no \n - */ c = ungetc (c, InFile); /* push back the EOF and */ c = '\n'; /* process the last line. */ } break; } if ((i < (MAXLINE - 1)) && (c != 13)) { /* Ignore excess */ if (c != '\t') Line[i++] = c; /* Normal character */ else { j = (i + 8) & ~7; /* Expand tabs */ if (j > (MAXLINE - 1)) j = MAXLINE - 1; /* Tabbed off the end */ while (i < j) Line[i++] = ' '; } } } Line[i] = '\0'; } if ((Line[0] != '\0') && (Line[0] != '*') && (Line[0] != ';')) { /* -------- Macro argument substitution routine -------- */ i = 0; while ((Line[i] != '\0') && (InF->NArg != -1)) { if ((subline[i] = Line[i]) != '\\') { i++; continue; } if (Line[i+1] == '@') { /* \@ - substitute macro number */ subline[i] = '.'; j = InF->MCnt % 1000; subline[i+1] = j / 100 + '0'; j = j % 100; subline[i+2] = j / 10 + '0'; subline[i+3] = j % 10 + '0'; subline[i+4] = '\0'; strcat (subline, &Line[i+2]); /* Remainder of Line */ strcpy (Line, subline); /* Replace Line */ i = 0; /* Check for more */ continue; } if (Line[i+1] < '0' || Line[i+1] > '9') { continue; /* False alarm */ } subline[i++] = '\0'; /* Chop off first portion */ j = 0; /* Get argument index */ while ((Line[i] >= '0') && (Line[i] <= '9')) { j *= 10; j += Line[i++] - '0'; /* Current digit */ } if ((j > 0) && (j <= InF->NArg)) { argptr = InF->NPtr; while (j > 0) { /* Find argument */ argptr += strlen (argptr) + 1; j--; } strcat (subline, argptr); /* Insert it */ } strcat (subline, &Line[i]); /* Remainder of Line */ strcpy (Line, subline); /* Replace Line */ i = 0; /* Check for more */ } /* ------- Break up Line into its component parts ------- */ i = 0; if (Line[i] != ' ') i = GetField (Line, i, Label); /* Label */ while ((j = strlen(Label)) > 0) { if (Label[j-1] != ':') break; Label[j-1] = '\0'; /* Strip trailing colon(s) */ } while (Line[i] == ' ') i++; if (Line[i] != ';') { OpLoc = i; i = GetField (Line, i, OpCode); /* Mnemonic */ while (Line[i] == ' ') i++; if ((Line[i] != ';') && (Line[i] != '\0')) { SrcLoc = i; i = GetField (Line, i, SrcOp); /* Op1 (source) */ if (Line[i] == ',') i++; if ((Line[i]!=' ') && (Line[i]!='\0') && (Line[i]!=';')) { DestLoc = i; i = GetField (Line, i, DestOp); /* Op2 (dest.) */ } } } } if ((j = strlen (OpCode)) == 0) Size = S0; else { Size = GetSize (OpCode); /* Instruction operand size */ for (i = 0; i < j; i++) /* Convert OpCode */ OpCode[i] = toupper(OpCode[i]); /* to upper case */ } /* ------ If we have reached the end of a macro or ------ */ /* ------ include file, return to the calling file ------ */ i = (c == EOF); /* End of file */ if ((Dir != Macro) && (SkipNest == 0)) { /* Macro exits */ i |= (strcmp (OpCode, "ENDM") == 0); i |= (strcmp (OpCode, "MEXIT") == 0); } if (!i) { /* Not end of file or macro */ if ((PrevDir == MacCall) && (strcmp (OpCode, "MACRO") == 0)) continue; /* Ignore macro header */ if (SkipNest == 0) /* We're not skipping */ break; /* We got something */ else { if (strcmp (OpCode, "ENDC") == 0) SkipNest--; else if (strcmp (OpCode, "IFEQ") == 0) SkipNest++; else if (strcmp (OpCode, "IFNE") == 0) SkipNest++; else if (strcmp (OpCode, "IFGT") == 0) SkipNest++; else if (strcmp (OpCode, "IFGE") == 0) SkipNest++; else if (strcmp (OpCode, "IFLT") == 0) SkipNest++; else if (strcmp (OpCode, "IFLE") == 0) SkipNest++; else if (strcmp (OpCode, "IFC" ) == 0) SkipNest++; else if (strcmp (OpCode, "IFNC") == 0) SkipNest++; else if (strcmp (OpCode, "IFD" ) == 0) SkipNest++; else if (strcmp (OpCode, "IFND") == 0) SkipNest++; continue; } } if (InFNum == 0) break; /* End of source file */ if (InF->UPtr == 0) { fclose (InFile); /* Close inner file */ InFile = NULL; } NextFNS = InF->NPtr; /* Release space on name stack */ InFNum--; /* Return to outer file */ InF++; if (InFNum < OuterMac) OuterMac = 0; /* End of outer macro */ if ((InF->UPtr == 0) && (InFile == NULL)) { InFile = fopen (InF->NPtr, "r"); fseek (InFile, InF->Pos, 0); } } LineCount++; /* Bump line counter */ (InF->Line)++; if (Label[0] != '\0') if ((Label[0] < '0') || (Label[0] > '9')) LabLine = LineCount; /* Save line number of label */ if ((LineCount % 10) == 0) { printf ("%4d\b\b\b\b", LineCount); /* Display progress */ #ifdef AZTEC_C fflush (stdout); /* Make sure it gets out */ #endif } errlim = AddrAdv = InstSize = nO = nS = nD = nX = 0; PrntAddr = FALSE; return (c == EOF); } int GetField (source, pos, dest) char source[], dest[]; int pos; /* Gets a field from "source", starting at position "pos". Result is returned in "dest". Stops on the first comma, semicolon, or white space not enclosed within apostrophes or parentheses. Returns stopping location. If already at end of "source", "dest" is set to null string. */ { register char *s; register int j, parncnt, instring; s = source + pos; /* Use a pointer for speed */ instring = FALSE; parncnt = j = 0; while (*s) { if (instring) { dest[j++] = *s; } else { if ((*s == ' ') || (*s == ';')) break; else if ((*s == ',') && (parncnt == 0)) break; else dest[j++] = *s; } if (*s == '(') parncnt++; else if (*s == ')') parncnt--; else if (*s == '\'') instring = !instring; s++; } dest[j] = '\0'; return (s - source); } AddMacLine (line) char *line; /* Adds the line in "line" to the heap. */ { HeapSpace (strlen (line) + 1); /* Make sure we have room */ strcpy (HeapLim, line); /* Store the line */ HeapLim += strlen (line) + 1; /* Update heap limit */ } long GetValue (operand, loc) char operand[]; int loc; /* Determines value of expression */ /* Hunk2 is set to hunk number of result (ABSHUNK if absolute). If the expression consists solely of self-defining terms, DefLine2 is set to zero. Otherwise, DefLine2 is set to the highest statement number in which any symbol in the expression was defined. If the expression contains any undefined symbols, DefLine2 is set to 32767. The following code is based on a regular-to-Polish expression converter described in "A Guide to FORTRAN IV Programming" by Daniel D. McCracken (John Wiley & Sons, Inc. 1965, 3rd printing August 1968). However, rather than generating the entire Polish expression, this routine will evaluate and combine two terms as soon as an operator of lower precedence is encountered. */ { register char *o, *s; char tempop[MAXLINE]; int oloc, parncnt, nextprec, instring; long templong; struct TermStack *origterm; Hunk2 = ABSHUNK; parncnt = DefLine2 = 0; o = NextFNS; if ((templong = (o - Heap) & 3L) != 0) o += 4 - templong; origterm = Term = (struct TermStack *) o; /* Term stack */ Ops = (struct OpStack *) InF; /* Operator stack */ Ops--; ParseSpace (0); Ops->chr = ' '; /* Prime the operator stack */ Ops->prec = -1; if ((char *) Ops < Low2) Low2 = (char *) Ops; /* Get all tokens. Terms are evaluated, and operator precedence is determined. Left and right parentheses are given a precedence of 1 and 2 respectively. Binary operators are given precedence values starting at 3. Unary plus is ignored. Unary minus is converted to zero minus the remainder of of the expression - its precedence is set to 9 to ensure that the simulated unary operator is evaluated before the remainder of the expression. Logical not (~), being another unary operator, is converted to -1 exclusive-ORed with the remainder of the expression. Its precedence is also set to 9. */ o = operand; /* Current position in operand */ while (1) { while (*o == '(') { /* Left parenthesis */ Ops--; ParseSpace (0); Ops->chr = '('; Ops->prec = 1; if ((char *) Ops < Low2) Low2 = (char *) Ops; parncnt++; o++; } if ((*o == '+') || (*o == '-') || (*o == '~')) { /* Unary op */ if (*o != '+') { /* Ignore unary plus */ Ops--; ParseSpace (sizeof (struct TermStack)); Term->value = (*o == '-') ? 0 : -1; /* Dummy value */ Term->hunk = ABSHUNK; Term->oploc = loc + (o - operand); Term->defline = 0; Term++; if ((char *) Term > High2) High2 = (char *) Term; Ops->chr = *o; /* Now get the operator itself */ Ops->prec = 9; /* Do it ASAP */ if ((char *) Ops < Low2) Low2 = (char *) Ops; } o++; if (*o == '(') continue; /* Inner parenthesized expression */ } oloc = loc + (o - operand); s = tempop; /* Get a term */ if (*o == '*') { /* It's a location counter reference, */ *s++ = *o++; /* not a multiplication operator! */ } else { if (IsOperator (o) || (*o == '\0')) { Error (oloc, OperErr); /* Unexpected operator or no terms */ return (0L); } instring = FALSE; while (*o) { if (*o == '\'') instring = !instring; /* String delimiter */ if (!instring && (IsOperator (o) || (*o == '~'))) break; /* Found an operator - stop */ *s++ = *o++; /* Get a character */ } } *s = '\0'; ParseSpace (sizeof (struct TermStack)); Term->value = CalcValue (tempop, oloc); Term->hunk = Hunk2; Term->oploc = oloc; Term->defline = DefLine2; Term++; if ((char *) Term > High2) High2 = (char *) Term; Hunk2 = DefLine2 = 0; while (*o == ')') { /* Right parenthesis */ if (parncnt == 0) { Error ((int) (loc + (o - operand)), OperErr); return (0L); } CondCalc (2); /* Unstack what we can */ if (Ops->chr == '(') Ops++; /* Drop paired parentheses */ else { Ops--; ParseSpace (0); Ops->chr = ')'; /* Stack parenthesis for now */ Ops->prec = 2; if ((char *) Ops < Low2) Low2 = (char *) Ops; } parncnt--; o++; } if (*o) { if (!IsOperator (o) || (*o == '(')) { Error ((int) (loc + (o - operand)), OperErr); return (0L); /* Expected an operator */ } switch (*o) { case '+': nextprec = 3; break; case '-': nextprec = 3; break; case '*': nextprec = 4; break; case '/': nextprec = 4; break; case '&': nextprec = 5; break; case '!': nextprec = 5; break; case '<': nextprec = 6; break; case '>': nextprec = 6; break; } CondCalc (nextprec); /* Unstack what we can */ Ops--; ParseSpace (0); Ops->chr = *o; /* Stack the next operator */ Ops->prec = nextprec; if ((char *) Ops < Low2) Low2 = (char *) Ops; if ((*o == '<') || (*o == '>')) o++; /* Skip over two-character operator */ o++; } else { if (parncnt) { Error ((int) (loc + (o - operand)), OperErr); return (0L); /* Too many left parentheses */ } CondCalc (0); /* Unstack what's left */ if (--Term != origterm) /* Should be only one term left */ Error (Term->oploc, OperErr); /* Parser bug? */ Hunk2 = Term->hunk; DefLine2 = Term->defline; return (Term->value); /* Final value */ } } } CondCalc (newprec) int newprec; /* As long as the top operator on the operator stack has a precedence greater than or equal to the contents of "newprec", this routine will pop the two top terms from the term stack, combine them according to the operator on the top of the operator stack (which is also popped), and push the result back onto the term stack. */ { while (Ops->prec >= newprec) { /* Unstack an operator */ Term -= 2; if (Ops->chr == '+') { /* Relocatable addition */ if (Term->hunk == ABSHUNK) Term->hunk = (Term+1)->hunk; /* A+R */ else if ((Term+1)->hunk != ABSHUNK) { Error ((Term+1)->oploc, RelErr); /* R+R - error */ Term->hunk = ABSHUNK; /* Make it absolute */ } } else if (Ops->chr == '-') { /* Subtraction */ if (Term->hunk == (Term+1)->hunk) Term->hunk = ABSHUNK; /* R-R - absolute */ else if (Term->hunk != ABSHUNK) { /* R-R across hunks */ Error ((Term+1)->oploc, RelErr); /* is an error - */ Term->hunk = ABSHUNK; /* make it absolute */ } } else if ((Term->hunk != ABSHUNK) || ((Term+1)->hunk != ABSHUNK)) { Error (Term->oploc,RelErr); /* All other operations */ Term->hunk = ABSHUNK; /* must be absolute */ } if ((Term+1)->defline > Term->defline) /* Definition */ Term->defline = (Term+1)->defline; /* line nos. */ switch (Ops->chr) { /* Perform the operation */ case '+': Term->value += (Term+1)->value; break; case '-': Term->value -= (Term+1)->value; break; case '*': Term->value *= (Term+1)->value; break; case '/': if ((Term+1)->value) Term->value /= (Term+1)->value; else Term->value = 0; /* Don't divide by zero */ break; case '&': Term->value &= (Term+1)->value; break; case '!': Term->value |= (Term+1)->value; break; case '<': Term->value <<= (Term+1)->value; break; case '>': Term->value >>= (Term+1)->value; break; case '~': Term->value ^= (Term+1)->value; break; default: Error (Term->oploc, OperErr); /* Parser bug? */ break; } Term++; Ops++; } } int IsOperator (o) char *o; /* Tests whether "o" points to a valid operator or parenthesis. */ { return ((*o == '+') || (*o == '-') || (*o == '*') || (*o == '/') || (*o == '&') || (*o == '!') || ((*o == '<') && (*(o+1) == '<')) || ((*o == '>') && (*(o+1) == '>')) || (*o == '(') || (*o == ')')); } long CalcValue (operand, loc) char operand[]; int loc; /* Evaluates a single term (called by GetValue). Hunk2 receives relative hunk number (ABSHUNK if absolute). If the value is a symbol, DefLine2 is set to the line number where it was defined, or 32767 if it is undefined. For self-defining terms, DefLine2 is set to zero. */ { register long result; /* Result is calculated here */ register int i, radix; int neg, numstart, local; char maxdig; /* Highest valid digit in current radix */ local = FALSE; if (neg = (operand[0] == '-')) numstart = 1; /* Negative value */ else { numstart = 0; /* Positive value */ i = strlen(operand) - 1; if (operand[i] == '$') { local = TRUE; /* Assume it's a local label */ while (i > 0) { i--; if ((operand[i] < '0') || (operand[i] > '9')) { local = FALSE; /* False alarm */ break; } } } } Hunk2 = ABSHUNK; /* Assume value is absolute */ DefLine2 = 0; /* and self-defining */ if ((operand[numstart] >= '0') && (operand[numstart] <= '9')) { radix = 10; /* Decimal number */ maxdig = '9'; } else if (operand[numstart] == '$') { radix = 16; /* Hexadecimal number */ maxdig = '9'; } else if (operand[numstart] == '@') { radix = 8; /* Octal number */ maxdig = '7'; } else if (operand[numstart] == '%') { radix = 2; /* Binary number */ maxdig = '1'; } else radix = 0; /* Not a number */ if (local) radix = 0; /* Local variable - not a number */ if (radix != 0) { /* Some sort of number */ result = 0; if (radix != 10) numstart++; /* Allow for type character */ for (i = numstart; operand[i] != '\0'; i++) { result *= radix; if ((operand[i] >= '0') && (operand[i] <= maxdig)) result += (operand[i] - '0'); else if (radix == 16) if ((operand[i] >= 'A') && (operand[i] <= 'F')) result += (operand[i] - 'A' + 10); else if ((operand[i] >= 'a') && (operand[i] <= 'f')) result += (operand[i] - 'a' + 10); else Error (loc + i, OperErr); else Error (loc + i, OperErr); } } else if (operand[0] == '\'') { /* Character value */ result = 0; for (i = 1; operand[i] != '\''; i++) { if (operand[i] == '\0') { Error (loc + i, OperErr); /* End is missing */ break; } result = (result << 8) + operand[i]; } } else if ((operand[0] == '*') && (operand[1] == '\0')) { result = AddrCnt; /* Value of location counter */ Hunk2 = CurrHunk; /* Use current section's hunk number */ } else if (strcmp (operand, "NARG") == 0) { result = InF->NArg; /* Number of arguments */ if (result == -1) result = 0; /* No arguments outside macros */ } else { if (ReadSymTab (operand)) { /* Look up symbol */ AddRef (LineCount); /* Found - add reference */ if (Sym->Flags & 0x60) Error (loc, AddrErr); /* Can't use a register equate */ } else Error (loc, Undef); /* Undefined */ result = Value; } if (neg) { result = -result; /* Negative value */ if (Hunk2 != ABSHUNK) Error (loc, RelErr); /* Must be absolute */ } return(result); } AddSymTab (label, value, hunk, line, flags) char label[]; long value, hunk; int line, flags; /* Inserts a new entry to the symbol table and updates NumSyms. The insertion position is taken from "Sym" - it must be such that the table will be kept in sequence by label. "Sym" is set by "ReadSymTab". If the label is a local label (i.e. the first character is numeric), the current contents of LabLine will be converted to characters and appended to the label before it is added. */ { register char *pj1, *pj2, *psym; char wlab[MAXLINE], wnum[6]; strcpy (wlab, label); if ((label[0] >= '0') && (label[0] <= '9')) { sprintf (wnum, "%d", LabLine); /* If it's a local label, */ strcat (wlab, wnum); /* append LabLine */ } pj2 = (char *) SymStart; SymStart--; pj1 = (char *) SymStart; HeapSpace (strlen(wlab)+1); /* Make sure we have room */ psym = (char *) Sym; /* Try for some speed */ while (pj2 < psym) /* Shift the table */ *pj1++ = *pj2++; Sect--; /* Adjust section pointer */ Sym--; /* Insert to left of search point */ Sym->Nam = HeapLim; /* Pointer to symbol */ Sym->Val = value; /* Value */ Sym->Hunk = hunk; /* Hunk number */ Sym->Defn = line; /* Statement number */ Sym->Flags = flags; /* Flags */ Sym->Ref1 = 0; /* Reference pointer */ NumSyms++; /* Count symbols */ strcpy (HeapLim, wlab); /* Store the symbol */ HeapLim += strlen(wlab)+1; /* Update heap limit */ } int ReadSymTab (label) char label[]; /* Searches the symbol table for the given label. If not found, points Sym to where the new entry should be inserted and returns FALSE. If found, points Sym to the proper table entry, and sets up the following fields: Value - value of symbol Hunk2 - hunk number in which symbol resides ABSHUNK if value is absolute ones complement of symbol table index if external DefLine2 - statement number in which symbol was defined (32767 if undefined ) If the label is a local label (i.e. the first character is numeric), the current contents of LabLine will be converted to characters and appended to the label before it is searched. */ { register int lower, upper, mid, search; char wlab[MAXLINE], wnum[6]; strcpy (wlab, label); if ((label[0] >= '0') && (label[0] <= '9')) { sprintf (wnum, "%d", LabLine); /* If it's a local label, */ strcat (wlab, wnum); /* append LabLine */ } for (lower = 0, upper = NumSyms; lower < upper; ) { mid = (lower + upper) / 2; Sym = SymStart + mid; search = strcmp (wlab, Sym->Nam); if (search < 0) upper = mid; else if (search > 0) lower = mid + 1; else { Value = Sym->Val; /* Found it */ Hunk2 = Sym->Hunk & 0x0000FFFFL; if (Hunk2 & 0x00008000L) Hunk2 |= 0xFFFF0000L; /* Extend sign */ DefLine2 = Sym->Defn; return (TRUE); } } Value = 0; /* Didn't find it - */ Hunk2 = ABSHUNK; /* set value to absolute zero */ DefLine2 = 32767; Sym = SymStart + lower; /* Insert a new entry here */ return (FALSE); } AddRef (linenum) int linenum; /* Adds "linenum" to the list of references for the symbol pointed to by Sym. */ { register int i; register struct Ref *ref, *prevref; if (!Pass2) return; /* Pass 2 only! */ if (!XrefList) return; /* No cross-reference */ prevref = 0; ref = Sym->Ref1; while (ref) { /* Chase pointers */ for (i = 0; i < MAXREF; i++) { /* Scan reference entry */ if (ref->RefNum[i] == 0) { /* for an empty slot */ ref->RefNum[i] = linenum; /* Insert new line number */ return; } } prevref = ref; /* Remember where we were */ ref = ref->NextRef; /* Link to the next entry */ } HeapSpace (sizeof (struct Ref)); /* Find space for a new entry */ RefStart--; RefStart->NextRef = 0; /* Pointer to next entry */ RefStart->RefNum[0] = linenum; /* First reference in new entry */ for (i = 1; i < MAXREF; i++) RefStart->RefNum[i] = 0; /* Clear remaining slots */ if (prevref == 0) Sym->Ref1 = RefStart; /* Link to first entry */ else prevref->NextRef = RefStart; /* Link to next entry */ } int GetSize (symbol) char symbol[]; /* Determines size of opcode/operand: Byte, Word, Long */ { register int i; register char c; i = 0; while (1) { c = symbol[i++]; if ((c == '\0') || (c == '.')) break; } if (c == '\0') return(Word); /* Default to size Word = 16 bits */ else { c = toupper (symbol[i]); /* Record size extension */ symbol[i - 1] = '\0'; /* Chop size extension off */ if ((c == 'B') || (c == 'S')) /* Byte or Short Branch/Jump */ return(Byte); else if (c == 'L') /* Long */ return(Long); else return(Word); /* Default to Word */ } } HeapSpace (n) int n; /* Die if we can't find "n" bytes of free space on the heap. */ { if ((HeapLim + n) > (Pass2 ? (char *) RefStart : (char *) SymStart)) { printf (" \n%4d %s\n", LineCount, Line); printf ("Primary heap overflow - assembly terminated.\n"); free (Heap); free (Heap2); exit(20); } } Heap2Space (n) int n; /* Works like HeapSpace, but on the secondary heap. */ { if ((NextFNS + n) > (char *) InF) { printf (" \n%4d %s\n", LineCount, Line); printf ("Secondary heap overflow - assembly terminated.\n"); free (Heap); free (Heap2); exit(20); } } ParseSpace (n) int n; /* Special version of Heap2Space for the expression parser */ { if (((char *) Term + n) > (char *) Ops) { printf (" \n%4d %s\n", LineCount, Line); printf ("Secondary heap overflow - assembly terminated.\n"); free (Heap); free (Heap2); exit(20); } }