/*------------------------------------------------------------------*/ /* */ /* MC68000 Cross Assembler */ /* */ /* Copyright (c) 1985 by Brian R. Anderson */ /* */ /* Main program - January 10, 1989 */ /* */ /* 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 1989 by Charlie Gibbs. */ /* */ /*------------------------------------------------------------------*/ char Version[] = "2.42 (January 10, 1989)"; #include #define PRIMARY #include "a68kdef.h" #include "a68kglb.h" #ifdef MSDOS /********************************************************************/ /* */ /* NOTE: the following line, plus any additional references */ /* to _iomode, is inserted to make this program work under */ /* the MS-DOS version of Lattice C. It is not necessary */ /* for the Amiga version, but does no harm if left in. */ /* */ /********************************************************************/ int _iomode = 0; /* File mode - 0x8000 for binary */ #endif /* Functions */ extern int LineParts(), Instructions(), ObjDir(); extern int GetInstModeSize(), GetMultReg(), CountNest(); extern int ReadSymTab(), GetArgs(), GetAReg(), OpenIncl(); extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue (); extern char *AddName(), *GetField(); extern struct SymTab *NextSym(); extern struct SymTab **HashIt(); main (argc,argv) int argc; char *argv[]; { char ListFN[MAXFN], EquateFN[MAXFN]; /* File names */ int makeequ; /* Make an equate file */ int keepobj; /* Keep object file with errors */ int endfile; /* End-of-file flag */ long maxheap2; /* Maximum secondary heap size */ int cmderror, dummy; long codesize, datasize, bsssize; int *intptr; long templong; char tempchar[MAXLINE]; register struct SymTab *sym; register int i, j; struct SymTab **hashptr; Hash = NULL; /* Clear all memory pointers - */ SymStart = NULL; /* we haven't allocated anything yet. */ NameStart = NULL; RelStart = NULL; Heap2 = NULL; SymSort = NULL; In.fd = Eq.fd = List.fd = Srec.fd = NULL; /* No files are open yet */ In.Buf = Eq.Buf = List.Buf = Srec.Buf = NULL; cmderror = FALSE; /* Clear command-line error flag */ InclErrs = FALSE; SourceFN[0] = '\0'; /* Don't have source name yet */ HeaderFN[0] = EquateFN[0] = '\0'; /* No header or equate files yet */ makeequ = FALSE; ListFN[0] = SrecFN[0] = '\0'; /* Indicate default file names */ InclList[0] = '\0'; /* Clear the include directory list */ IdntName[0] = '\0'; /* Clear program unit name */ LnMax = 60; Quiet = 10; /* Show progress every 10 lines */ strcpy (MacSize, "W"); /* Macro call size (\0) */ XrefList = DumpSym = GotEqur = KeepTabs = keepobj = FALSE; SuppList = TRUE; /* Default to no listing file */ HashStats = FALSE; /* Default to no hashing statistics */ HashSize = DEFHASH; /* Hash table size default */ maxheap2 = DEFHEAP2; /* Secondary heap size default */ DebugStart = 32767; DebugEnd = 0; /* Disable debug displays */ for (i = 0; i < 256; i++) OpPrec[i] = '\0'; /* Set up the operator precedence table */ i = (unsigned int) '('; OpPrec[i] = 1; i = (unsigned int) ')'; OpPrec[i] = 2; i = (unsigned int) '+'; OpPrec[i] = 3; i = (unsigned int) '-'; OpPrec[i] = 3; i = (unsigned int) '*'; OpPrec[i] = 4; i = (unsigned int) '/'; OpPrec[i] = 4; i = (unsigned int) '&'; OpPrec[i] = 5; i = (unsigned int) '!'; OpPrec[i] = 5; i = (unsigned int) '|'; OpPrec[i] = 5; i = (unsigned int) '<'; OpPrec[i] = 6; i = (unsigned int) '>'; OpPrec[i] = 6; printf ("68000 Assembler - version %s\n", Version); printf ("Copyright 1985 by Brian R. Anderson\n"); printf ("AmigaDOS conversion copyright 1989 by Charlie Gibbs.\n\n"); for (i = 1; i < argc; i++) { /* Analyze command line */ if (argv[i][0] != '-') { if (SourceFN[0] == '\0') strcpy (SourceFN, argv[i]); /* Source file name */ else if (SrecFN[0] == '\0') strcpy (SrecFN, argv[i]); /* Object file name */ else if (ListFN[0] == '\0') strcpy (ListFN, argv[i]); /* Listing file name */ else { fprintf (stderr, "Too many file names.\n"); cmderror = TRUE; } } else { switch (toupper(argv[i][1])) { case 'D': /* Dump the symbol table */ DumpSym = TRUE; cmderror |= checkswitch (argv[i][2], "symbol table dump"); break; case 'E': /* Equate file name */ makeequ = TRUE; if (getfilename (EquateFN, &argv[i][2], "Equate", FALSE)) cmderror = keepobj = TRUE; break; case 'F': /* Dump the symbol table */ FwdProc = TRUE; cmderror |= checkswitch (argv[i][2], "forward reference"); break; case 'H': /* Header file name */ if (getfilename (HeaderFN, &argv[i][2], "Header", TRUE)) cmderror = keepobj = TRUE; break; case 'I': /* Include directories */ if (argv[i][2]) { if (InclList[0]) strcat (InclList, ","); /* Add to previous list */ strcat (InclList, &argv[i][2]); } else { fprintf (stderr, "Include directory list is missing.\n"); cmderror = keepobj = TRUE; } break; case 'K': /* Keep object code file */ keepobj = TRUE; cmderror |= checkswitch (argv[i][2], "object file keep"); break; case 'X': /* Cross-reference listing */ XrefList = TRUE; /* Falls through to case 'L': */ case 'L': /* Produce a listing file */ SuppList = FALSE; if (getfilename (ListFN, &argv[i][2], "List", FALSE)) cmderror = keepobj = TRUE; break; case 'O': /* Object file name */ if (getfilename (SrecFN, &argv[i][2], "Object", TRUE)) cmderror = keepobj = TRUE; break; case 'P': /* Page depth */ if (argv[i][2] == '\0') { fprintf (stderr, "Page depth is missing.\n"); cmderror = keepobj = TRUE; break; } if ((LnMax = CalcValue (&argv[i][2], 0)) < 10) { fprintf (stderr, "Page depth is invalid.\n"); cmderror = TRUE; } break; case 'Q': /* Quiet console display */ Quiet = CalcValue (&argv[i][2], 0); break; case 'S': /* Motorola S-format */ SFormat = TRUE; cmderror |= checkswitch (argv[i][2], "S-format"); break; case 'T': /* Keep tabs in listing */ KeepTabs = TRUE; cmderror |= checkswitch (argv[i][2], "tab"); break; case 'W': /* Work storage size(s) */ if (argv[i][2] == '\0') { fprintf (stderr, "Work storage size is missing.\n"); cmderror = keepobj = TRUE; break; } if (argv[i][2] != ',') { GetField (argv[i]+2, tempchar); HashSize = CalcValue (tempchar, 0); if (HashSize >= 16384) { fprintf (stderr, "Hash table size is too big.\n"); cmderror = TRUE; } } for (j = 2; argv[i][j]; j++) { if (argv[i][j] == ',') { /* Find secondary size */ maxheap2 = CalcValue (&argv[i][j+1], 0); if (maxheap2 < MAXLINE) maxheap2 = MAXLINE; maxheap2 &= ~3L; break; } } break; case 'Y': /* Display hashing statistics */ HashStats = TRUE; cmderror |= checkswitch (argv[i][2], "hash statistics"); break; case 'Z': /* Debug option */ DebugStart = 0; DebugEnd = 32767; if (argv[i][2] != ',') { /* Debug dump starts here */ GetField (argv[i]+2, tempchar); DebugStart = CalcValue (tempchar, 0); } for (j = 2; argv[i][j]; j++) { if (argv[i][j] == ',') { /* Debug dump ends here */ DebugEnd = CalcValue (&argv[i][j+1], 0); if (DebugEnd == 0) DebugEnd = 32767; } } break; default: fprintf (stderr, "Unrecognized switch: %c\n", argv[i][1]); cmderror = TRUE; break; } } } if (makeequ) defaultfile (EquateFN, ".equ"); /* Default equate file name */ if (!SuppList) defaultfile (ListFN, ".lst"); /* Default list file name */ else /* If there's no listing, don't bother */ KeepTabs = TRUE; /* expanding tabs - it's faster. */ if (SFormat) defaultfile (SrecFN, ".s"); /* Default S-format file name */ else defaultfile (SrecFN, ".o"); /* Default object file name */ /* Check for duplicate file names. */ if (SourceFN[0]) { cmderror |= checkdupfile (SourceFN, "Source", EquateFN, "equate"); cmderror |= checkdupfile (SourceFN, "Source", ListFN, "listing"); cmderror |= checkdupfile (SourceFN, "Source", SrecFN, "object"); } else { fprintf (stderr, "Source file name is missing.\n"); cmderror = TRUE; } if (EquateFN[0]) { cmderror |= checkdupfile (EquateFN, "Equate", ListFN, "listing"); cmderror |= checkdupfile (EquateFN, "Equate", SrecFN, "object"); } if (ListFN[0]) { cmderror |= checkdupfile (ListFN, "Listing", SrecFN, "object"); } /* Open files. */ if (!cmderror) { /* Source file */ if ((In.Buf = (char *) malloc (BUFFSIZE)) == NULL) quit_cleanup ("Out of memory!\n"); #ifdef MSDOS _iomode = 0x8000; #endif if ((In.fd = open (SourceFN, 0)) == -1) { fprintf (stderr, "Unable to open source file.\n"); In.fd = NULL; cmderror = TRUE; } In.Ptr = In.Lim = In.Buf; } #ifdef MSDOS _iomode = 0; #endif if (!cmderror && EquateFN[0]) /* Equate file */ cmderror |= xopen (EquateFN, &Eq, "equate"); if (!cmderror && !SuppList) /* Listing file */ cmderror |= xopen (ListFN, &List, "listing"); #ifdef MSDOS if (!SFormat) _iomode = 0x8000; #endif if (!cmderror) /* Object code file */ cmderror |= xopen (SrecFN, &Srec, "object code"); #ifdef MSDOS _iomode = 0x8000; #endif if (cmderror) { fprintf (stderr, "\n"); fprintf (stderr, "Usage: a68k \n"); fprintf (stderr, " [-e]\n"); fprintf (stderr, " [-h
]\n"); fprintf (stderr, " [-i]\n"); fprintf (stderr, " [-l]\n"); fprintf (stderr, " [-o]\n"); fprintf (stderr, " [-p]\n"); fprintf (stderr, " [-q[]]\n"); fprintf (stderr, " [-w[][,]]\n"); fprintf (stderr, " [-z[][,]]\n"); fprintf (stderr, " [-d] [-f] [-k] [-s] [-t] [-x] [-y]\n\n"); fprintf (stderr, "Command-line arguments can appear in any order.\n"); fprintf (stderr, "Heap size default: -w"); fprintf (stderr, "%ld,%ld\n", (long) DEFHASH, (long) DEFHEAP2); if (keepobj) SrecFN[0] = '\0'; /* Don't scratch object file! */ quit_cleanup ("\n"); } printf ("Assembling %s\n\n", SourceFN); /* Allocate initial symbol table chunks. */ templong = sizeof (struct SymTab *) * HashSize; Hash = (struct SymTab **) malloc ((unsigned) templong); if (Hash == NULL) quit_cleanup ("Out of memory!\n"); for (hashptr = Hash, i = 0; i < HashSize; hashptr++, i++) *hashptr = NULL; /* Clear the hash table */ SymStart = (struct SymTab *) malloc ((unsigned) CHUNKSIZE); if (SymStart == NULL) quit_cleanup ("Out of memory!\n"); SymCurr = SymStart; /* Make the first chunk current */ SymCurr->Link = NULL; /* Clear forward pointer */ SymLim = SymCurr; SymLim++; /* Start of names */ NameStart = (struct NameChunk *) malloc ((unsigned) CHUNKSIZE); if (NameStart == NULL) quit_cleanup ("Out of memory!\n"); NameCurr = NameStart; /* Make the first chunk current */ NameCurr->Link = NULL; /* Clear forward pointer */ NameLim = (char *) NameCurr + sizeof (char *); /* Start of names */ /* Allocate the relocation attribute table. */ RelStart = (struct RelTab *) malloc ((unsigned) CHUNKSIZE); if (RelStart == NULL) quit_cleanup ("Out of memory!\n"); RelCurr = RelStart; /* Relocation table */ RelCurr->Link = NULL; /* No additional chunks */ RelLast = NULL; /* There are no entries yet */ RelLim = RelStart; RelLim++; /* First unused space */ /* Allocate the secondary heap (input files and parser stack). */ Heap2 = malloc ((unsigned) maxheap2); if (Heap2 == NULL) quit_cleanup ("Out of memory!\n"); /* Allocate the INCLUDE skip table. */ SkipLim = (struct SkipEnt *) malloc ((unsigned) INCSKSIZ); if (SkipLim == NULL) quit_cleanup ("Out of memory!\n"); SkipIdx = SkipLim; SetFixLim = (struct SetFixup *) ((char *) SkipLim + INCSKSIZ); IncStart = 0; /*------------------------------------------------------------------- Begin Pass 1. */ Pass2 = FALSE; startpass ('1', maxheap2); NumSyms = 0; /* There's nothing in the symbol table yet */ NextHunk = 0L; /* Start in hunk zero */ LowInF = InF; /* Initialize secondary heap usage pointers */ High2 = NextFNS; Low2 = (char *) LowInF; /* Define ".A68K" as a SET symbol with an absolute value of 1. This allows programs to identify this assembler. */ AddSymTab (".A68K", 1L, (long) ABSHUNK, 0, 4); /* All spellings */ AddSymTab (".A68k", 1L, (long) ABSHUNK, 0, 4); AddSymTab (".a68K", 1L, (long) ABSHUNK, 0, 4); AddSymTab (".a68k", 1L, (long) ABSHUNK, 0, 4); endfile = FALSE; Dir = None; while (!endfile && (Dir != End)) { PrevDir = Dir; /* Save previous directive */ endfile = LineParts (dummy); /* Get a statement */ GetObjectCode (dummy); /* Process the statement */ if (IncStart != 0) { if ((OpCode[0] != '\0') && (Dir < SkipDir)) { IncStart = 0; /* We can't */ if (SkipLim->Set1 != NULL) { /* skip this */ SetFixLim = SkipLim->Set1; /* INCLUDE file */ SetFixLim++; /* in pass 2. */ } } } if ((HunkType == HunkNone) && (AddrAdv != 0)) { DoSection ("", 0, "", 0, "", 0); /* Start unnamed CODE section */ MakeHunk = TRUE; } if ((Label[0] != '\0') /* If statement is labeled */ && (Dir != Set) && (Dir != Equr) && (Dir != Reg)) { if (!ReadSymTab (Label)) { /* Make a new entry */ AddSymTab (Label, AddrCnt, CurrHunk, LineCount, 0); } else if ((Sym->Flags & 1) /* If dup., ignore */ || (Sym->Defn == NODEF)) { /* else fill in */ Sym->Val = AddrCnt; /* Current loc. */ Sym->Hunk = CurrHunk; /* Hunk number */ Sym->Defn = LineCount; /* Statement number */ Sym->Flags &= ~1; /* Clear XREF flag */ if (Sym->Flags & 0x80) { /* If it's PUBLIC, */ Sym->Flags |= 2; /* make it XDEF */ } } if (Dir == Equ) { Sym->Val = ObjSrc; /* Equated value */ Sym->Hunk = Src.Hunk; /* Hunk number */ } } AddrCnt += AddrAdv; /* Advance location counter */ } if ((HunkType == HunkNone) && (NumSyms != 0)) { /* Dummy section */ DoSection ("", 0, "", 0, "", 0); /* to get XDEF */ MakeHunk = TRUE; /* symbols if any */ } if (HunkType != HunkNone) if (AddrCnt > OrgHigh) Sect->Val = AddrCnt; /* End of the last section */ else Sect->Val = OrgHigh; /* We've ORGed higher */ if (InclErrs) quit_cleanup ("Fatal errors - assembly aborted\n"); if (Quiet >= 0) fprintf (stderr, "%d\n", LineCount); else fprintf (stderr, "%d\n\n", InF->Line); /*---------------------------------------------------------------- Begin Pass 2. */ Pass2 = TRUE; lseek (In.fd, 0L, 0); /* "Rewind" the source file */ In.Ptr = In.Lim = In.Buf; startpass ('2', maxheap2); RefLim = (struct Ref *) SymLim; /* Cross-reference table */ /* Calculate the total size of each section type, reset all section pointers to the beginning, and write all absolute symbols to an equate file if desired. */ codesize = datasize = bsssize = 0; if (EquateFN[0]) { xputs (&Eq, "* Equate file for "); xputs (&Eq, SourceFN); xputs (&Eq, "\n* Created by"); xputs (&Eq, " A68k version "); xputs (&Eq, Version); xputs (&Eq, "\n"); } Sym = SymChunk = SymStart; Sym++; SymChLim = (struct SymTab *) ((char *) SymChunk + CHUNKSIZE); while (Sym) { if (Sym->Flags & 0x10) { templong = (Sym->Val + 3) & ~3L; /* Hunk size */ j = (Sym->Hunk & 0x3FFF0000L) >> 16; /* Hunk type */ if (j == HunkCode) /* Accumulate sizes by type */ codesize += templong; else if (j == HunkData) datasize += templong; else bsssize += templong; Sym->Val = 0L; /* Back to start of all sections */ } if (EquateFN[0]) { if (((Sym->Hunk & 0x00007FFFL) == ABSHUNK) && ((Sym->Flags == 0) || (Sym->Flags == 2))) { xputs (&Eq, Sym->Nam); xputs (&Eq, "\tEQU\t$"); LongPut (&Eq, Sym->Val, 4); xputs (&Eq, "\n"); } } Sym = NextSym (Sym); /* Try for another symbol table entry */ } if (EquateFN[0]) xclose (&Eq); /* Write sign-on messages for listing file */ LnCnt = LnMax; PgCnt = 0; if (!SuppList) { CheckPage (&List, FALSE); /* Print headings */ xputs (&List, "68000 Assembler - version "); xputs (&List, Version); xputs (&List, "\nCopyright 1985 by Brian R. Anderson.\n"); xputs (&List, "AmigaDOS conversion copyright 1989"); xputs (&List, " by Charlie Gibbs.\n\n"); LnCnt += 4; } StartSrec (&Srec, IdntName); /* Write object header record */ /* Process the second pass. */ endfile = FALSE; Dir = None; while (!endfile && (Dir != End)) { PrevDir = Dir; /* Save previous directive */ endfile = LineParts (dummy); /* Get a statement */ if (!endfile) { GetObjectCode (dummy); /* Process the statement */ if (Label[0] != '\0') { /* If statement is labeled, */ ReadSymTab (Label); /* check for duplicate defn. */ if (Sym->Defn != LineCount) { AddRef (LineCount); /* Got one - flag as reference */ if (Dir == Set) { if ((Sym->Flags & 4) == 0) Error (LabLoc, SymDup); /* Can't SET normal label */ } else { Error (LabLoc, SymDup); /* Ordinary duplicate */ } } else if (Dir == Set) { AddRef (LineCount); /* Flag all SETs as references */ } else { if (Sym->Val != AddrCnt) if ((Dir != Equ) && (Dir != Equr) && (Dir != Reg)) Error (0, Phase); /* Assembler error */ } } WriteListLine (&List); WriteSrecLine (&Srec); AddrCnt += AddrAdv; /* Advance location counter */ } else { Error (0, EndErr); /* END statement is missing */ WriteListLine (&List); } } if ((HunkType == HunkNone) && (NumSyms != 0)) { /* Dummy section */ DoSection ("", 0, "", 0, "", 0); /* to get XDEF */ MakeHunk = TRUE; /* symbols if any */ } /*--------------------------------------------------------------------- Clean up. */ if (HunkType != HunkNone) if (AddrCnt > OrgHigh) Sect->Val = AddrCnt; /* End of the last section */ else Sect->Val = OrgHigh; /* We've ORGed higher */ if (Quiet >= 0) fprintf (stderr, "%d", LineCount); /* Final line number */ else fprintf (stderr, "%d\n", InF->Line); fflush (stderr); /* Make sure it gets out */ close (In.fd); /* Finished with source file */ In.fd = NULL; free (In.Buf); In.Buf = NULL; EndSdata (&Srec, EndAddr); /* Write remaining data and end record */ xclose (&Srec); /* Finished with object file */ if ((ErrorCount != 0) && (!keepobj)) unlink (SrecFN); /* Scratch it if there were errors */ RelCurr = RelStart; while (RelCurr != NULL) { RelLim = RelCurr; RelCurr = RelCurr->Link; free (RelLim); /* Free the relocation table */ RelCurr = NULL; } if (Heap2 != NULL) { free (Heap2); /* Free the secondary heap */ Heap2 = NULL; } if (XrefList) WriteSymTab (&List); /* List the symbol table */ /* Display final error count. */ fprintf (stderr, "\nEnd of assembly - "); if (!SuppList) xputs (&List, "\nEnd of assembly - "); if (ErrorCount == 0) { fprintf (stderr, "no errors were found.\n"); if (!SuppList) xputs (&List, "no errors were found.\n"); } else if (ErrorCount == 1) { fprintf (stderr, "1 error was found.\n"); if (!SuppList) xputs (&List, "1 error was found.\n"); } else { fprintf (stderr, "%d errors were found.\n", ErrorCount); if (!SuppList) { sprintf (tempchar, "%d errors were found.\n", ErrorCount); xputs (&List, tempchar); } } /* Display heap usage. */ fprintf (stderr, "Heap usage: -w%ld", HashSize); if (!SuppList) { sprintf (tempchar, "Heap usage: -w%ld", HashSize); xputs (&List, tempchar); } templong = (long) (High2 - Heap2); if (Low2 < (char *) LowInF) templong += (long) (Heap2 + maxheap2 - Low2); else templong += (long) (Heap2 + maxheap2 - (char *) LowInF); fprintf (stderr, ",%ld\n", templong); if (!SuppList) { sprintf (tempchar, ",%ld\n", templong); xputs (&List, tempchar); } /* Display the total size of all section types. */ fprintf (stderr, "Total hunk sizes: %lx code, ", codesize); fprintf (stderr, "%lx data, %lx BSS\n", datasize, bsssize); if (!SuppList) { sprintf (tempchar, "Total hunk sizes: %lx code, ", codesize); xputs (&List, tempchar); sprintf (tempchar, "%lx data, %lx BSS\n", datasize, bsssize); xputs (&List, tempchar); } /* Display hashing statistics if required. */ if (HashStats && (NumSyms != 0)) { printf ("\n"); printf ("HASH CHAIN STATISTICS - %d symbols\n\n", NumSyms); templong = (NumSyms + 1) * sizeof (int); HashCount = (int *) malloc ((unsigned) templong); if (HashCount == NULL) quit_cleanup ("Out of memory!\n"); printf ("Length No. of chains\n"); printf ("------ -------------\n"); intptr = HashCount; for (i = 0; i <= NumSyms; i++) *(intptr++) = 0; /* Clear hash chain length counters */ hashptr = Hash; for (i = 0; i < HashSize; i++) { j = 0; if ((Sym = *hashptr) != NULL) { j++; /* This chain has at least one entry */ while ((Sym = Sym->Link) != NULL) { j++; /* Count entries in the chain */ } } intptr = HashCount + j; (*intptr)++; /* Bump counter by chain length */ hashptr++; } intptr = HashCount; for (i = 0; i <= NumSyms; i++) { if (*intptr) printf ("%4d %4d\n", i, *intptr); intptr++; } free (HashCount); /* Free hash statistics table */ HashCount = NULL; } /* All done! */ if (!SuppList) { xputs (&List, "\f"); /* One last page eject */ xclose (&List); /* Finished with listing file */ } quit_cleanup (""); /* Normal termination */ } /*======================================================================*/ /* */ /* Subroutines used by the main program */ /* */ /*======================================================================*/ int getfilename (name, arg, desc, needit) char *name, *arg, *desc; int needit; /* If "name" is not a duplicate, copies "arg" to it, else flags duplicate using "desc". If "needit" is TRUE, also flags an error if "arg" is a null string. Returns TRUE if an error is found, FALSE otherwise. */ { if (*name) { fprintf (stderr, "%s file is declared more than once.\n", desc); return (TRUE); } if (*arg) { strcpy (name, arg); return (FALSE); } if (needit) { fprintf (stderr, "%s file name is missing\n", desc); return (TRUE); } return (FALSE); } int checkswitch (c, name) char c, *name; /* Displays an error message and returns TRUE if "c" isn't a NULL. Just returns FALSE otherwise. */ { if (c) { fprintf (stderr, "Invalid %s switch.\n", name); return (TRUE); } else { return (FALSE); } } defaultfile (name, ext) char *name, *ext; /* If "name" is a null string, search for the last period in "name" (if any) and append "ext". If "name" doesn't contain a period, append a period and "ext". */ { char *s; if (*name == '\0') { /* If name isn't specified... */ strcpy (name,SourceFN); /* Start with source file name */ s = name+strlen(name); /* Scan backwards for period */ while (--s > name) { if (*s == '.') { *s = '\0'; /* Chop off name extension */ break; } } strcat (name, ext); /* Add name extension */ } } int checkdupfile (name1, desc1, name2, desc2) char *name1, *desc1, *name2, *desc2; /* If "name1" is the same as "name2", display an error message using "desc1" and "desc2" and return TRUE. Otherwise, return FALSE. */ { if (strcmp (name1, name2) == 0) { fprintf (stderr, "%s and %s file names are the same.\n", desc1, desc2); return (TRUE); } else { return (FALSE); } } startpass (pchar, maxheap2) char pchar; long maxheap2; /* Set up to start the next pass. */ { int dummy; if (Quiet >= 0) { fprintf (stderr, "PASS %c line ", pchar); fflush (stderr); } else { fprintf (stderr, "PASS %c\n", pchar); } NextFNS = Heap2; InF = (struct InFCtl *) (Heap2 + maxheap2); InF--; InFNum = OuterMac = SkipNest = InF->Pos = InF->MCnt = 0; InF->Line = 0; InF->UPtr = 0; InF->NPtr = NextFNS; InF->NArg = -1; InF->MCnt = 0; strcpy (NextFNS, SourceFN); ShowFile (FALSE); /* Show source file name */ NextFNS += strlen (SourceFN) + 1; LineCount = LabLine = MacCount = ErrorCount = 0; AddrCnt = CurrHunk = SectStart = EndAddr = 0L; HunkType = HunkNone; /* We're not in a hunk yet */ HunkFlags = SectLine = HunkSeq = 0; ListOff = MakeHunk = InnrFMac = SmallData = FALSE; TTLstring[0] = '\0'; /* Clear the title string */ } quit_cleanup (s) char *s; /* Clean up and exit. */ { if (In.fd != NULL) /* Close all files */ close (In.fd); if (In.Buf != NULL) /* and free buffers */ free (In.Buf); if (Srec.fd != NULL) xclose (&Srec); if (List.fd != NULL) xclose (&List); if (Eq.fd != NULL) xclose (&Eq); if (Hash != NULL) free (Hash); /* Free the hash table */ SymCurr = SymStart; while (SymCurr != NULL) { SymLim = SymCurr; SymCurr = SymCurr->Link; free (SymLim); /* Free the symbol table */ } NameCurr = NameStart; while (NameCurr != NULL) { NameLim = (char *) NameCurr; NameCurr = NameCurr->Link; free (NameLim); /* Free the name table */ } RelCurr = RelStart; while (RelCurr != NULL) { RelLim = RelCurr; RelCurr = RelCurr->Link; free (RelLim); /* Free the relocation table */ } if (Heap2 != NULL) free (Heap2); /* Free the secondary heap */ if (SymSort != NULL) free (SymSort); /* Free symbol table sort area */ if (HashCount != NULL) free (HashCount); /* Free hash statistics table */ if (*s) { /* If we have an error message, */ if (SrecFN[0]) unlink (SrecFN); /* scratch the object file, */ fprintf (stderr, "%s", s); /* display the error message, */ exit (20); /* and die. */ } else { exit (ErrorCount ? 10 : 0); /* Normal termination */ } }