home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------*/
- /* */
- /* 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 <stdio.h>
- #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);
- }
- }
-