home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d186 / a68k.lha / A68k / A68kmain.c < prev    next >
C/C++ Source or Header  |  1989-02-26  |  28KB  |  883 lines

  1. /*------------------------------------------------------------------*/
  2. /*                                    */
  3. /*              MC68000 Cross Assembler                */
  4. /*                                    */
  5. /*           Copyright (c) 1985 by Brian R. Anderson            */
  6. /*                                    */
  7. /*           Main    program    - January 10, 1989            */
  8. /*                                    */
  9. /*   This program may be copied    for personal, non-commercial use    */
  10. /*   only, provided that the above copyright notice is included        */
  11. /*   on    all copies of the source code.    Copying    for any    other use   */
  12. /*   without the consent of the    author is prohibited.            */
  13. /*                                    */
  14. /*------------------------------------------------------------------*/
  15. /*                                    */
  16. /*        Originally published (in Modula-2) in            */
  17. /*        Dr.    Dobb's Journal, April, May, and June 1986.          */
  18. /*                                    */
  19. /*     AmigaDOS conversion copyright 1989 by Charlie Gibbs.        */
  20. /*                                    */
  21. /*------------------------------------------------------------------*/
  22.  
  23. char Version[] = "2.42 (January 10, 1989)";
  24.  
  25.  
  26. #include <stdio.h>
  27. #define    PRIMARY
  28. #include "a68kdef.h"
  29. #include "a68kglb.h"
  30.  
  31.  
  32. #ifdef MSDOS
  33. /********************************************************************/
  34. /*                                    */
  35. /*     NOTE: the following line, plus any additional references        */
  36. /*     to _iomode, is inserted to make this program work under        */
  37. /*     the MS-DOS version of Lattice C.     It is not necessary        */
  38. /*     for the Amiga version, but does no harm if left in.        */
  39. /*                                    */
  40. /********************************************************************/
  41. int _iomode = 0;    /* File    mode - 0x8000 for binary */
  42. #endif
  43.  
  44.  
  45.  
  46. /* Functions */
  47. extern int  LineParts(), Instructions(), ObjDir();
  48. extern int  GetInstModeSize(), GetMultReg(), CountNest();
  49. extern int  ReadSymTab(), GetArgs(), GetAReg(),    OpenIncl();
  50. extern long AddrBndW(),    AddrBndL(), GetValue(),    CalcValue ();
  51. extern char *AddName(),    *GetField();
  52. extern struct SymTab *NextSym();
  53. extern struct SymTab **HashIt();
  54.  
  55.  
  56.  
  57. main (argc,argv) int argc; char    *argv[];
  58. {
  59.     char ListFN[MAXFN],    EquateFN[MAXFN]; /* File names */
  60.     int     makeequ;            /* Make    an equate file */
  61.     int     keepobj;            /* Keep    object file with errors    */
  62.     int     endfile;            /* End-of-file flag */
  63.     long maxheap2;            /* Maximum secondary heap size */
  64.     int     cmderror, dummy;
  65.     long codesize, datasize, bsssize;
  66.     int     *intptr;
  67.     long templong;
  68.     char tempchar[MAXLINE];
  69.     register struct SymTab *sym;
  70.     register int i, j;
  71.     struct SymTab **hashptr;
  72.  
  73.     Hash = NULL;    /* Clear all memory pointers - */
  74.     SymStart = NULL;    /*  we haven't allocated anything yet. */
  75.     NameStart =    NULL;
  76.     RelStart = NULL;
  77.     Heap2 = NULL;
  78.     SymSort = NULL;
  79.     In.fd = Eq.fd = List.fd = Srec.fd =    NULL;    /* No files are    open yet */
  80.     In.Buf = Eq.Buf = List.Buf = Srec.Buf = NULL;
  81.  
  82.     cmderror = FALSE;        /* Clear command-line error flag */
  83.     InclErrs = FALSE;
  84.     SourceFN[0]    = '\0';                 /* Don't have source name yet */
  85.     HeaderFN[0]    = EquateFN[0] =    '\0';   /* No header or equate files yet */
  86.     makeequ = FALSE;
  87.     ListFN[0] =    SrecFN[0] = '\0';       /* Indicate default file names */
  88.     InclList[0]    = '\0';         /* Clear the include directory list */
  89.     IdntName[0]    = '\0';         /* Clear program unit name */
  90.     LnMax = 60;
  91.     Quiet = 10;            /* Show    progress every 10 lines    */
  92.     strcpy (MacSize, "W");      /* Macro call size (\0) */
  93.     XrefList = DumpSym = GotEqur = KeepTabs = keepobj =    FALSE;
  94.     SuppList = TRUE;        /* Default to no listing file */
  95.     HashStats =    FALSE;        /* Default to no hashing statistics */
  96.     HashSize = DEFHASH;        /* Hash    table size default */
  97.     maxheap2 = DEFHEAP2;    /* Secondary heap size default */
  98.     DebugStart = 32767;    DebugEnd = 0;    /* Disable debug displays */
  99.  
  100.     for    (i = 0;    i < 256; i++)
  101.     OpPrec[i] = '\0';       /* Set up the operator precedence table */
  102.     i =    (unsigned int) '('; OpPrec[i] = 1;
  103.     i =    (unsigned int) ')'; OpPrec[i] = 2;
  104.     i =    (unsigned int) '+'; OpPrec[i] = 3;
  105.     i =    (unsigned int) '-'; OpPrec[i] = 3;
  106.     i =    (unsigned int) '*'; OpPrec[i] = 4;
  107.     i =    (unsigned int) '/'; OpPrec[i] = 4;
  108.     i =    (unsigned int) '&'; OpPrec[i] = 5;
  109.     i =    (unsigned int) '!'; OpPrec[i] = 5;
  110.     i =    (unsigned int) '|'; OpPrec[i] = 5;
  111.     i =    (unsigned int) '<'; OpPrec[i] = 6;
  112.     i =    (unsigned int) '>'; OpPrec[i] = 6;
  113.  
  114.     printf ("68000 Assembler - version %s\n", Version);
  115.     printf ("Copyright 1985 by Brian R. Anderson\n");
  116.     printf ("AmigaDOS conversion copyright 1989 by Charlie Gibbs.\n\n");
  117.  
  118.     for    (i = 1;    i < argc; i++) {    /* Analyze command line    */
  119.     if (argv[i][0] != '-') {
  120.         if (SourceFN[0] == '\0')
  121.         strcpy (SourceFN, argv[i]);    /* Source file name */
  122.         else if (SrecFN[0] == '\0')
  123.         strcpy (SrecFN,    argv[i]);    /* Object file name */
  124.         else if (ListFN[0] == '\0')
  125.         strcpy (ListFN,    argv[i]);    /* Listing file    name */
  126.         else {
  127.         fprintf    (stderr, "Too many file names.\n");
  128.         cmderror = TRUE;
  129.         }
  130.     } else {
  131.         switch (toupper(argv[i][1])) {
  132.         case 'D':                   /* Dump the symbol table */
  133.         DumpSym     = TRUE;
  134.         cmderror |= checkswitch    (argv[i][2], "symbol table dump");
  135.         break;
  136.         case 'E':                   /* Equate file name */
  137.         makeequ    = TRUE;
  138.         if (getfilename    (EquateFN, &argv[i][2],    "Equate", FALSE))
  139.             cmderror = keepobj = TRUE;
  140.         break;
  141.         case 'F':                   /* Dump the symbol table */
  142.         FwdProc     = TRUE;
  143.         cmderror |= checkswitch    (argv[i][2], "forward reference");
  144.         break;
  145.         case 'H':                   /* Header file name */
  146.         if (getfilename    (HeaderFN, &argv[i][2],    "Header", TRUE))
  147.             cmderror = keepobj = TRUE;
  148.         break;
  149.         case 'I':                   /* Include directories */
  150.         if (argv[i][2])    {
  151.             if (InclList[0])
  152.             strcat (InclList, ","); /* Add to previous list */
  153.             strcat (InclList, &argv[i][2]);
  154.         } else {
  155.             fprintf (stderr, "Include directory list is missing.\n");
  156.             cmderror = keepobj = TRUE;
  157.         }
  158.         break;
  159.         case 'K':                   /* Keep object code file */
  160.         keepobj     = TRUE;
  161.         cmderror |= checkswitch    (argv[i][2], "object file keep");
  162.         break;
  163.         case 'X':                   /* Cross-reference listing */
  164.         XrefList = TRUE;    /* Falls through to case 'L': */
  165.         case 'L':                   /* Produce a listing file */
  166.         SuppList = FALSE;
  167.         if (getfilename    (ListFN, &argv[i][2], "List", FALSE))
  168.             cmderror = keepobj = TRUE;
  169.         break;
  170.         case 'O':                   /* Object file name */
  171.         if (getfilename    (SrecFN, &argv[i][2], "Object", TRUE))
  172.             cmderror = keepobj = TRUE;
  173.         break;
  174.         case 'P':                   /* Page depth */
  175.         if (argv[i][2] == '\0') {
  176.             fprintf (stderr, "Page depth is missing.\n");
  177.             cmderror = keepobj = TRUE;
  178.             break;
  179.         }
  180.         if ((LnMax = CalcValue (&argv[i][2], 0)) < 10) {
  181.             fprintf (stderr, "Page depth is invalid.\n");
  182.             cmderror = TRUE;
  183.         }
  184.         break;
  185.         case 'Q':                   /* Quiet console display */
  186.         Quiet =    CalcValue (&argv[i][2],    0);
  187.         break;
  188.         case 'S':                   /* Motorola S-format */
  189.         SFormat    = TRUE;
  190.         cmderror |= checkswitch    (argv[i][2], "S-format");
  191.         break;
  192.         case 'T':                   /* Keep tabs in listing */
  193.         KeepTabs = TRUE;
  194.         cmderror |= checkswitch    (argv[i][2], "tab");
  195.         break;
  196.         case 'W':                   /* Work storage size(s) */
  197.         if (argv[i][2] == '\0') {
  198.             fprintf (stderr, "Work storage size is missing.\n");
  199.             cmderror = keepobj = TRUE;
  200.             break;
  201.         }
  202.         if (argv[i][2] != ',') {
  203.             GetField (argv[i]+2, tempchar);
  204.             HashSize = CalcValue (tempchar, 0);
  205.             if (HashSize >= 16384) {
  206.             fprintf    (stderr, "Hash table size is too big.\n");
  207.             cmderror = TRUE;
  208.             }
  209.         }
  210.         for (j = 2; argv[i][j];    j++) {
  211.             if (argv[i][j] == ',') {    /* Find secondary size */
  212.             maxheap2 = CalcValue (&argv[i][j+1], 0);
  213.             if (maxheap2 < MAXLINE)
  214.                 maxheap2 = MAXLINE;
  215.             maxheap2 &= ~3L;
  216.             break;
  217.             }
  218.         }
  219.         break;
  220.         case 'Y':                   /* Display hashing statistics */
  221.         HashStats = TRUE;
  222.         cmderror |= checkswitch    (argv[i][2], "hash statistics");
  223.         break;
  224.         case 'Z':                   /* Debug option */
  225.         DebugStart = 0;
  226.         DebugEnd = 32767;
  227.         if (argv[i][2] != ',') {        /* Debug dump starts here */
  228.             GetField (argv[i]+2, tempchar);
  229.             DebugStart = CalcValue (tempchar, 0);
  230.         }
  231.         for (j = 2; argv[i][j];    j++) {
  232.             if (argv[i][j] == ',') {    /* Debug dump ends here */
  233.             DebugEnd = CalcValue (&argv[i][j+1], 0);
  234.             if (DebugEnd ==    0)
  235.                 DebugEnd = 32767;
  236.             }
  237.         }
  238.         break;
  239.         default:
  240.         fprintf    (stderr, "Unrecognized switch: %c\n", argv[i][1]);
  241.         cmderror = TRUE;
  242.         break;
  243.         }
  244.     }
  245.     }
  246.  
  247.     if (makeequ)
  248.     defaultfile (EquateFN, ".equ"); /* Default equate file name */
  249.     if (!SuppList)
  250.     defaultfile (ListFN, ".lst");   /* Default list file name */
  251.     else            /* If there's no listing, don't bother */
  252.     KeepTabs = TRUE;    /*  expanding tabs - it's faster.      */
  253.     if (SFormat)
  254.     defaultfile (SrecFN, ".s");     /* Default S-format file name */
  255.     else
  256.     defaultfile (SrecFN, ".o");     /* Default object file name */
  257.  
  258. /* Check for duplicate file names. */
  259.  
  260.     if (SourceFN[0]) {
  261.     cmderror |= checkdupfile (SourceFN, "Source", EquateFN, "equate");
  262.     cmderror |= checkdupfile (SourceFN, "Source", ListFN, "listing");
  263.     cmderror |= checkdupfile (SourceFN, "Source", SrecFN, "object");
  264.     } else {
  265.     fprintf    (stderr, "Source file name is missing.\n");
  266.     cmderror = TRUE;
  267.     }
  268.     if (EquateFN[0]) {
  269.     cmderror |= checkdupfile (EquateFN, "Equate", ListFN, "listing");
  270.     cmderror |= checkdupfile (EquateFN, "Equate", SrecFN, "object");
  271.     }
  272.     if (ListFN[0]) {
  273.     cmderror |= checkdupfile (ListFN, "Listing", SrecFN, "object");
  274.     }
  275.  
  276. /*    Open files.    */
  277.  
  278.     if (!cmderror) {                /* Source file */
  279.     if ((In.Buf = (char *) malloc (BUFFSIZE)) == NULL)
  280.         quit_cleanup ("Out of memory!\n");
  281. #ifdef MSDOS
  282.     _iomode    = 0x8000;
  283. #endif
  284.     if ((In.fd = open (SourceFN, 0)) == -1)    {
  285.         fprintf (stderr, "Unable to open source file.\n");
  286.         In.fd = NULL;
  287.         cmderror = TRUE;
  288.     }
  289.     In.Ptr = In.Lim    = In.Buf;
  290.     }
  291. #ifdef MSDOS
  292.     _iomode = 0;
  293. #endif
  294.     if (!cmderror && EquateFN[0])        /* Equate file */
  295.     cmderror |= xopen (EquateFN, &Eq, "equate");
  296.  
  297.     if (!cmderror && !SuppList)            /* Listing file    */
  298.     cmderror |= xopen (ListFN, &List, "listing");
  299.  
  300. #ifdef MSDOS
  301.     if (!SFormat)
  302.     _iomode    = 0x8000;
  303. #endif
  304.     if (!cmderror)                /* Object code file */
  305.     cmderror |= xopen (SrecFN, &Srec, "object code");
  306. #ifdef MSDOS
  307.     _iomode = 0x8000;
  308. #endif
  309.  
  310.     if (cmderror) {
  311.     fprintf    (stderr, "\n");
  312.     fprintf    (stderr, "Usage: a68k <source file>\n");
  313.     fprintf    (stderr, "            [-e<equate file>]\n");
  314.     fprintf    (stderr, "            [-h<header file>]\n");
  315.     fprintf    (stderr, "            [-i<include dirlist>]\n");
  316.     fprintf    (stderr, "            [-l<listing file>]\n");
  317.     fprintf    (stderr, "            [-o<object file>]\n");
  318.     fprintf    (stderr, "            [-p<page depth>]\n");
  319.     fprintf    (stderr, "            [-q[<quiet interval>]]\n");
  320.     fprintf    (stderr, "            [-w[<hash size>][,<heap size>]]\n");
  321.     fprintf    (stderr, "            [-z[<debug start>][,<debug end>]]\n");
  322.     fprintf    (stderr, "            [-d] [-f] [-k] [-s] [-t] [-x] [-y]\n\n");
  323.     fprintf    (stderr, "Command-line arguments can appear in any order.\n");
  324.     fprintf    (stderr, "Heap size default:  -w");
  325.     fprintf    (stderr, "%ld,%ld\n", (long) DEFHASH, (long) DEFHEAP2);
  326.     if (keepobj)
  327.         SrecFN[0] =    '\0';   /* Don't scratch object file! */
  328.     quit_cleanup ("\n");
  329.     }
  330.  
  331.     printf ("Assembling %s\n\n", SourceFN);
  332.  
  333. /* Allocate initial symbol table chunks. */
  334.  
  335.     templong = sizeof (struct SymTab *)    * HashSize;
  336.     Hash = (struct SymTab **) malloc ((unsigned) templong);
  337.     if (Hash ==    NULL)
  338.     quit_cleanup ("Out of memory!\n");
  339.     for    (hashptr = Hash, i = 0;    i < HashSize; hashptr++, i++)
  340.     *hashptr = NULL;    /* Clear the hash table    */
  341.  
  342.     SymStart = (struct SymTab *) malloc    ((unsigned) CHUNKSIZE);
  343.     if (SymStart == NULL)
  344.     quit_cleanup ("Out of memory!\n");
  345.     SymCurr = SymStart;            /* Make    the first chunk    current    */
  346.     SymCurr->Link = NULL;        /* Clear forward pointer */
  347.     SymLim = SymCurr;
  348.     SymLim++;                /* Start of names */
  349.  
  350.     NameStart =    (struct    NameChunk *) malloc ((unsigned)    CHUNKSIZE);
  351.     if (NameStart == NULL)
  352.     quit_cleanup ("Out of memory!\n");
  353.     NameCurr = NameStart;        /* Make    the first chunk    current    */
  354.     NameCurr->Link = NULL;        /* Clear forward pointer */
  355.     NameLim = (char *) NameCurr    + sizeof (char *);  /* Start of    names */
  356.  
  357. /* Allocate the    relocation attribute table. */
  358.  
  359.     RelStart = (struct RelTab *) malloc    ((unsigned) CHUNKSIZE);
  360.     if (RelStart == NULL)
  361.     quit_cleanup ("Out of memory!\n");
  362.     RelCurr = RelStart;            /* Relocation table */
  363.     RelCurr->Link = NULL;        /* No additional chunks    */
  364.     RelLast = NULL;            /* There are no    entries    yet */
  365.     RelLim = RelStart;
  366.     RelLim++;                /* First unused    space */
  367.  
  368. /* Allocate the    secondary heap (input files and    parser stack). */
  369.  
  370.     Heap2 = malloc ((unsigned) maxheap2);
  371.     if (Heap2 == NULL)
  372.     quit_cleanup ("Out of memory!\n");
  373.  
  374. /* Allocate the    INCLUDE    skip table. */
  375.  
  376.     SkipLim = (struct SkipEnt *) malloc    ((unsigned) INCSKSIZ);
  377.     if (SkipLim    == NULL)
  378.     quit_cleanup ("Out of memory!\n");
  379.     SkipIdx = SkipLim;
  380.     SetFixLim =    (struct    SetFixup *) ((char *) SkipLim +    INCSKSIZ);
  381.     IncStart = 0;
  382.  
  383. /*-------------------------------------------------------------------
  384.  
  385.     Begin Pass 1.
  386.                                    */
  387.     Pass2 = FALSE;
  388.     startpass ('1', maxheap2);
  389.     NumSyms = 0;    /* There's nothing in the symbol table yet */
  390.     NextHunk = 0L;    /* Start in hunk zero */
  391.     LowInF = InF;    /* Initialize secondary    heap usage pointers */
  392.     High2 = NextFNS;
  393.     Low2  = (char *) LowInF;
  394.  
  395.     /* Define ".A68K" as a SET symbol with an absolute value of 1.
  396.     This allows programs to    identify this assembler.    */
  397.     AddSymTab (".A68K", 1L, (long) ABSHUNK, 0, 4);  /* All spellings */
  398.     AddSymTab (".A68k", 1L, (long) ABSHUNK, 0, 4);
  399.     AddSymTab (".a68K", 1L, (long) ABSHUNK, 0, 4);
  400.     AddSymTab (".a68k", 1L, (long) ABSHUNK, 0, 4);
  401.  
  402.     endfile = FALSE;
  403.     Dir    = None;
  404.     while (!endfile && (Dir != End)) {
  405.     PrevDir    = Dir;            /* Save    previous directive */
  406.     endfile    = LineParts (dummy);    /* Get a statement */
  407.     GetObjectCode (dummy);        /* Process the statement */
  408.  
  409.     if (IncStart !=    0) {
  410.         if ((OpCode[0] != '\0') && (Dir < SkipDir)) {
  411.         IncStart = 0;            /* We can't      */
  412.         if (SkipLim->Set1 != NULL) {    /*  skip this     */
  413.             SetFixLim =    SkipLim->Set1;    /*  INCLUDE file */
  414.             SetFixLim++;        /*  in pass 2.     */
  415.         }
  416.         }
  417.     }
  418.     if ((HunkType == HunkNone) && (AddrAdv != 0)) {
  419.         DoSection ("", 0, "", 0, "", 0);    /* Start unnamed CODE section */
  420.         MakeHunk = TRUE;
  421.     }
  422.     if ((Label[0] != '\0')                  /* If statement is labeled */
  423.     && (Dir    != Set)    && (Dir    != Equr) && (Dir != Reg)) {
  424.         if (!ReadSymTab (Label)) {        /* Make    a new entry */
  425.         AddSymTab (Label, AddrCnt, CurrHunk, LineCount,    0);
  426.         } else if ((Sym->Flags & 1)        /* If dup., ignore */
  427.         || (Sym->Defn == NODEF)) {        /* else    fill in    */
  428.         Sym->Val = AddrCnt;        /* Current loc.    */
  429.         Sym->Hunk = CurrHunk;        /* Hunk    number */
  430.         Sym->Defn = LineCount;        /* Statement number */
  431.         Sym->Flags &= ~1;        /* Clear XREF flag */
  432.         if (Sym->Flags & 0x80) {    /* If it's PUBLIC, */
  433.             Sym->Flags |= 2;        /*  make it XDEF */
  434.         }
  435.         }
  436.         if (Dir == Equ) {
  437.         Sym->Val = ObjSrc;        /* Equated value */
  438.         Sym->Hunk = Src.Hunk;        /* Hunk    number */
  439.         }
  440.     }
  441.     AddrCnt    += AddrAdv;    /* Advance location counter */
  442.     }
  443.     if ((HunkType == HunkNone) && (NumSyms != 0)) { /* Dummy section   */
  444.     DoSection ("", 0, "", 0, "", 0);            /*  to get XDEF    */
  445.     MakeHunk = TRUE;                /*    symbols    if any */
  446.     }
  447.     if (HunkType != HunkNone)
  448.     if (AddrCnt > OrgHigh)
  449.         Sect->Val =    AddrCnt;    /* End of the last section */
  450.     else
  451.         Sect->Val =    OrgHigh;    /* We've ORGed higher */
  452.  
  453.     if (InclErrs)
  454.     quit_cleanup ("Fatal errors - assembly aborted\n");
  455.  
  456.     if (Quiet >= 0)
  457.     fprintf    (stderr, "%d\n", LineCount);
  458.     else
  459.     fprintf    (stderr, "%d\n\n", InF->Line);
  460.  
  461.  
  462.  
  463. /*----------------------------------------------------------------
  464.  
  465.     Begin Pass 2.
  466.                                    */
  467.     Pass2 = TRUE;
  468.     lseek (In.fd, 0L, 0);        /* "Rewind" the source file */
  469.     In.Ptr = In.Lim = In.Buf;
  470.     startpass ('2', maxheap2);
  471.     RefLim = (struct Ref *) SymLim;    /* Cross-reference table */
  472.  
  473. /* Calculate the total size of each section type,
  474.     reset all section pointers to the beginning, and
  475.     write all absolute symbols to an equate file if desired. */
  476.  
  477.     codesize = datasize    = bsssize = 0;
  478.     if (EquateFN[0]) {
  479.     xputs (&Eq, "* Equate file for ");
  480.     xputs (&Eq, SourceFN);
  481.     xputs (&Eq, "\n* Created by");
  482.     xputs (&Eq, " A68k version ");
  483.     xputs (&Eq, Version);
  484.     xputs (&Eq, "\n");
  485.     }
  486.     Sym    = SymChunk = SymStart;
  487.     Sym++;
  488.     SymChLim = (struct SymTab *) ((char    *) SymChunk + CHUNKSIZE);
  489.     while (Sym)    {
  490.     if (Sym->Flags & 0x10) {
  491.         templong = (Sym->Val + 3) &    ~3L;        /* Hunk    size */
  492.         j =    (Sym->Hunk & 0x3FFF0000L) >> 16;    /* Hunk    type */
  493.         if (j == HunkCode)            /* Accumulate sizes    by type    */
  494.         codesize += templong;
  495.         else if (j == HunkData)
  496.         datasize += templong;
  497.         else
  498.         bsssize    += templong;
  499.         Sym->Val = 0L;    /* Back    to start of all    sections */
  500.     }
  501.     if (EquateFN[0]) {
  502.         if (((Sym->Hunk & 0x00007FFFL) == ABSHUNK)
  503.         && ((Sym->Flags == 0) || (Sym->Flags == 2))) {
  504.         xputs (&Eq, Sym->Nam);
  505.         xputs (&Eq, "\tEQU\t$");
  506.         LongPut    (&Eq, Sym->Val,    4);
  507.         xputs (&Eq, "\n");
  508.         }
  509.     }
  510.     Sym = NextSym (Sym);    /* Try for another symbol table    entry */
  511.     }
  512.     if (EquateFN[0])
  513.     xclose (&Eq);
  514.  
  515. /* Write sign-on messages for listing file */
  516.  
  517.     LnCnt = LnMax;
  518.     PgCnt = 0;
  519.     if (!SuppList) {
  520.     CheckPage (&List, FALSE);        /* Print headings */
  521.     xputs (&List, "68000 Assembler - version ");
  522.     xputs (&List, Version);
  523.     xputs (&List, "\nCopyright 1985 by Brian R. Anderson.\n");
  524.     xputs (&List, "AmigaDOS conversion copyright 1989");
  525.     xputs (&List, " by Charlie Gibbs.\n\n");
  526.     LnCnt += 4;
  527.     }
  528.  
  529.     StartSrec (&Srec, IdntName);    /* Write object    header record */
  530.  
  531. /*    Process    the second pass.    */
  532.  
  533.     endfile = FALSE;
  534.     Dir    = None;
  535.     while (!endfile && (Dir != End)) {
  536.     PrevDir    = Dir;            /* Save    previous directive */
  537.     endfile    = LineParts (dummy);    /* Get a statement */
  538.     if (!endfile) {
  539.         GetObjectCode (dummy);    /* Process the statement */
  540.         if (Label[0] != '\0') {     /* If statement is labeled, */
  541.         ReadSymTab (Label);    /*  check for duplicate    defn. */
  542.         if (Sym->Defn != LineCount) {
  543.             AddRef (LineCount);    /* Got one - flag as reference */
  544.             if (Dir == Set) {
  545.             if ((Sym->Flags    & 4) ==    0)
  546.                 Error (LabLoc, SymDup); /* Can't SET normal label */
  547.             } else {
  548.             Error (LabLoc, SymDup);    /* Ordinary duplicate */
  549.             }
  550.         } else if (Dir == Set) {
  551.             AddRef (LineCount);    /* Flag    all SETs as references */
  552.         } else {
  553.             if (Sym->Val != AddrCnt)
  554.             if ((Dir != Equ) && (Dir != Equr) && (Dir != Reg))
  555.                 Error (0, Phase);    /* Assembler error */
  556.         }
  557.         }
  558.         WriteListLine (&List);
  559.         WriteSrecLine (&Srec);
  560.         AddrCnt += AddrAdv;        /* Advance location counter */
  561.     } else {
  562.         Error (0, EndErr);        /* END statement is missing */
  563.         WriteListLine (&List);
  564.     }
  565.     }
  566.     if ((HunkType == HunkNone) && (NumSyms != 0)) { /* Dummy section   */
  567.     DoSection ("", 0, "", 0, "", 0);            /*  to get XDEF    */
  568.     MakeHunk = TRUE;                /*    symbols    if any */
  569.     }
  570.  
  571. /*---------------------------------------------------------------------
  572.  
  573.     Clean up.
  574.                                 */
  575.  
  576.     if (HunkType != HunkNone)
  577.     if (AddrCnt > OrgHigh)
  578.         Sect->Val =    AddrCnt;    /* End of the last section */
  579.     else
  580.         Sect->Val =    OrgHigh;    /* We've ORGed higher */
  581.  
  582.     if (Quiet >= 0)
  583.     fprintf    (stderr, "%d", LineCount);      /* Final line number */
  584.     else
  585.     fprintf    (stderr, "%d\n", InF->Line);
  586.     fflush (stderr);            /* Make    sure it    gets out */
  587.  
  588.     close (In.fd);        /* Finished with source    file */
  589.     In.fd = NULL;
  590.     free (In.Buf);
  591.     In.Buf = NULL;
  592.  
  593.     EndSdata (&Srec, EndAddr);    /* Write remaining data    and end    record */
  594.     xclose (&Srec);        /* Finished with object    file */
  595.     if ((ErrorCount != 0) && (!keepobj))
  596.     unlink (SrecFN);    /* Scratch it if there were errors */
  597.  
  598.     RelCurr = RelStart;
  599.     while (RelCurr != NULL) {
  600.     RelLim = RelCurr;
  601.     RelCurr    = RelCurr->Link;
  602.     free (RelLim);        /* Free    the relocation table */
  603.     RelCurr    = NULL;
  604.     }
  605.  
  606.     if (Heap2 != NULL) {
  607.     free (Heap2);        /* Free    the secondary heap */
  608.     Heap2 =    NULL;
  609.     }
  610.  
  611.     if (XrefList)
  612.     WriteSymTab (&List);    /* List    the symbol table */
  613.  
  614. /* Display final error count. */
  615.     fprintf (stderr, "\nEnd of assembly - ");
  616.     if (!SuppList)
  617.     xputs (&List, "\nEnd of assembly - ");
  618.     if (ErrorCount == 0) {
  619.     fprintf    (stderr, "no errors were found.\n");
  620.     if (!SuppList)
  621.         xputs (&List, "no errors were found.\n");
  622.     } else if (ErrorCount == 1)    {
  623.     fprintf    (stderr, "1 error was found.\n");
  624.     if (!SuppList)
  625.         xputs (&List, "1 error was found.\n");
  626.     } else {
  627.     fprintf    (stderr, "%d errors were found.\n", ErrorCount);
  628.     if (!SuppList) {
  629.         sprintf (tempchar, "%d errors were found.\n", ErrorCount);
  630.         xputs (&List, tempchar);
  631.     }
  632.     }
  633.  
  634. /* Display heap    usage. */
  635.     fprintf (stderr, "Heap usage:  -w%ld", HashSize);
  636.     if (!SuppList) {
  637.     sprintf    (tempchar, "Heap usage:  -w%ld", HashSize);
  638.     xputs (&List, tempchar);
  639.     }
  640.     templong = (long) (High2 - Heap2);
  641.     if (Low2 < (char *)    LowInF)
  642.     templong += (long) (Heap2 + maxheap2 - Low2);
  643.     else
  644.     templong += (long) (Heap2 + maxheap2 - (char *)    LowInF);
  645.     fprintf (stderr, ",%ld\n", templong);
  646.     if (!SuppList) {
  647.     sprintf    (tempchar, ",%ld\n", templong);
  648.     xputs (&List, tempchar);
  649.     }
  650.  
  651. /* Display the total size of all section types.    */
  652.     fprintf (stderr, "Total hunk sizes:  %lx code, ", codesize);
  653.     fprintf (stderr, "%lx data, %lx BSS\n", datasize, bsssize);
  654.     if (!SuppList) {
  655.     sprintf    (tempchar, "Total hunk sizes:  %lx code, ", codesize);
  656.     xputs (&List, tempchar);
  657.     sprintf    (tempchar, "%lx data, %lx BSS\n", datasize, bsssize);
  658.     xputs (&List, tempchar);
  659.     }
  660.  
  661. /* Display hashing statistics if required. */
  662.     if (HashStats && (NumSyms != 0)) {
  663.     printf ("\n");
  664.     printf ("HASH CHAIN STATISTICS - %d symbols\n\n", NumSyms);
  665.     templong = (NumSyms + 1) * sizeof (int);
  666.     HashCount = (int *) malloc ((unsigned) templong);
  667.     if (HashCount == NULL)
  668.         quit_cleanup ("Out of memory!\n");
  669.  
  670.     printf ("Length     No. of chains\n");
  671.     printf ("------     -------------\n");
  672.     intptr = HashCount;
  673.     for (i = 0; i <= NumSyms; i++)
  674.         *(intptr++)    = 0;    /* Clear hash chain length counters */
  675.  
  676.     hashptr    = Hash;
  677.     for (i = 0; i <    HashSize; i++) {
  678.         j =    0;
  679.         if ((Sym = *hashptr) != NULL) {
  680.         j++;        /* This    chain has at least one entry */
  681.         while ((Sym = Sym->Link) != NULL) {
  682.             j++;    /* Count entries in the    chain */
  683.         }
  684.         }
  685.         intptr = HashCount + j;
  686.         (*intptr)++;    /* Bump    counter    by chain length    */
  687.         hashptr++;
  688.     }
  689.     intptr = HashCount;
  690.     for (i = 0; i <= NumSyms; i++) {
  691.         if (*intptr)
  692.         printf ("%4d          %4d\n", i, *intptr);
  693.         intptr++;
  694.     }
  695.     free (HashCount);        /* Free    hash statistics    table */
  696.     HashCount = NULL;
  697.     }
  698.  
  699. /* All done! */
  700.     if (!SuppList) {
  701.     xputs (&List, "\f");    /* One last page eject */
  702.     xclose (&List);        /* Finished with listing file */
  703.     }
  704.     quit_cleanup ("");          /* Normal termination */
  705. }
  706.  
  707.  
  708.  
  709. /*======================================================================*/
  710. /*                                    */
  711. /*        Subroutines used by the    main program            */
  712. /*                                    */
  713. /*======================================================================*/
  714.  
  715.  
  716.  
  717. int getfilename    (name, arg, desc, needit)
  718. char *name, *arg, *desc;
  719. int needit;
  720. /* If "name" is not a duplicate, copies "arg" to it, else flags
  721.     duplicate using "desc".  If "needit" is TRUE, also flags
  722.     an error if    "arg" is a null string.
  723.     Returns TRUE if an error is    found, FALSE otherwise.    */
  724. {
  725.     if (*name) {
  726.     fprintf    (stderr, "%s file is declared more than once.\n", desc);
  727.     return (TRUE);
  728.     }
  729.     if (*arg) {
  730.     strcpy (name, arg);
  731.     return (FALSE);
  732.     }
  733.     if (needit)    {
  734.     fprintf    (stderr, "%s file name is missing\n", desc);
  735.     return (TRUE);
  736.     }
  737.     return (FALSE);
  738. }
  739.  
  740.  
  741.  
  742. int checkswitch    (c, name) char c, *name;
  743. /* Displays an error message and returns TRUE if "c" isn't a NULL.
  744.     Just returns FALSE otherwise.                */
  745. {
  746.     if (c) {
  747.     fprintf    (stderr, "Invalid %s switch.\n", name);
  748.     return (TRUE);
  749.     } else {
  750.     return (FALSE);
  751.     }
  752. }
  753.  
  754.  
  755.  
  756. defaultfile (name, ext)    char *name, *ext;
  757. /* If "name" is a null string, search for the last period in "name"
  758.     (if    any) and append    "ext".
  759.     If "name" doesn't contain a period, append a period and "ext". */
  760. {
  761.     char *s;
  762.  
  763.     if (*name == '\0') {        /* If name isn't specified... */
  764.     strcpy (name,SourceFN);    /* Start with source file name */
  765.     s = name+strlen(name);    /* Scan    backwards for period */
  766.     while (--s > name) {
  767.         if (*s == '.') {
  768.         *s = '\0';      /* Chop off name extension */
  769.         break;
  770.         }
  771.     }
  772.     strcat (name, ext);    /* Add name extension */
  773.     }
  774. }
  775.  
  776.  
  777.  
  778. int checkdupfile (name1, desc1,    name2, desc2)
  779. char *name1, *desc1, *name2, *desc2;
  780. /* If "name1" is the same as "name2", display an error message using
  781.     "desc1" and "desc2" and return TRUE.  Otherwise, return FALSE. */
  782. {
  783.     if (strcmp (name1, name2) == 0) {
  784.     fprintf    (stderr,
  785.         "%s and %s file names are the same.\n", desc1, desc2);
  786.     return (TRUE);
  787.     } else {
  788.     return (FALSE);
  789.     }
  790. }
  791.  
  792.  
  793.  
  794. startpass (pchar, maxheap2) char pchar;    long maxheap2;
  795. /* Set up to start the next pass. */
  796. {
  797.     int    dummy;
  798.  
  799.     if (Quiet >= 0) {
  800.     fprintf    (stderr, "PASS %c line ", pchar);
  801.     fflush (stderr);
  802.     } else {
  803.     fprintf    (stderr, "PASS %c\n", pchar);
  804.     }
  805.     NextFNS = Heap2;
  806.     InF    = (struct InFCtl *) (Heap2 + maxheap2);
  807.     InF--;
  808.     InFNum = OuterMac =    SkipNest = InF->Pos = InF->MCnt    = 0;
  809.     InF->Line =    0;
  810.     InF->UPtr =    0;
  811.     InF->NPtr =    NextFNS;
  812.     InF->NArg =    -1;
  813.     InF->MCnt =    0;
  814.     strcpy (NextFNS, SourceFN);
  815.     ShowFile (FALSE);            /* Show    source file name */
  816.     NextFNS += strlen (SourceFN) + 1;
  817.     LineCount =    LabLine    = MacCount = ErrorCount    = 0;
  818.     AddrCnt = CurrHunk = SectStart = EndAddr = 0L;
  819.     HunkType = HunkNone;        /* We're not in a hunk yet */
  820.     HunkFlags =    SectLine = HunkSeq = 0;
  821.     ListOff = MakeHunk = InnrFMac = SmallData =    FALSE;
  822.     TTLstring[0] = '\0';                /* Clear the title string */
  823. }
  824.  
  825.  
  826.  
  827. quit_cleanup (s) char *s;
  828. /* Clean up and    exit. */
  829. {
  830.     if (In.fd != NULL)            /* Close all files */
  831.     close (In.fd);
  832.     if (In.Buf != NULL)            /*  and    free buffers */
  833.     free (In.Buf);
  834.     if (Srec.fd    != NULL)
  835.     xclose (&Srec);
  836.     if (List.fd    != NULL)
  837.     xclose (&List);
  838.     if (Eq.fd != NULL)
  839.     xclose (&Eq);
  840.  
  841.     if (Hash !=    NULL)
  842.     free (Hash);            /* Free    the hash table */
  843.  
  844.     SymCurr = SymStart;
  845.     while (SymCurr != NULL) {
  846.     SymLim = SymCurr;
  847.     SymCurr    = SymCurr->Link;
  848.     free (SymLim);            /* Free    the symbol table */
  849.     }
  850.  
  851.     NameCurr = NameStart;
  852.     while (NameCurr != NULL) {
  853.     NameLim    = (char    *) NameCurr;
  854.     NameCurr = NameCurr->Link;
  855.     free (NameLim);            /* Free    the name table */
  856.     }
  857.  
  858.     RelCurr = RelStart;
  859.     while (RelCurr != NULL) {
  860.     RelLim = RelCurr;
  861.     RelCurr    = RelCurr->Link;
  862.     free (RelLim);            /* Free    the relocation table */
  863.     }
  864.  
  865.     if (Heap2 != NULL)
  866.     free (Heap2);            /* Free    the secondary heap */
  867.  
  868.     if (SymSort    != NULL)
  869.     free (SymSort);            /* Free    symbol table sort area */
  870.  
  871.     if (HashCount != NULL)
  872.     free (HashCount);        /* Free    hash statistics    table */
  873.  
  874.     if (*s) {                /* If we have an error message,    */
  875.     if (SrecFN[0])
  876.         unlink (SrecFN);        /*  scratch the    object file,    */
  877.     fprintf    (stderr, "%s", s);      /*  display the error message,  */
  878.     exit (20);            /*  and    die. */
  879.     } else {
  880.     exit (ErrorCount ? 10 :    0);    /* Normal termination */
  881.     }
  882. }
  883.