home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d110
/
a68k.lha
/
A68k
/
Symtab.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-10-28
|
28KB
|
924 lines
/*------------------------------------------------------------------*/
/* */
/* 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);
}
}