home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff287.lzh / DAsm / src / main.c < prev    next >
C/C++ Source or Header  |  1989-12-06  |  20KB  |  955 lines

  1.  
  2. /*
  3.  *  MAIN.C
  4.  *
  5.  *  (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
  6.  *     Freely Distributable (for non-profit) ONLY.  No redistribution
  7.  *     of any modified text files or redistribution of a subset of the
  8.  *     source is allowed.  Redistribution of modified binaries IS allowed
  9.  *     under the above terms.
  10.  *
  11.  *  DASM   sourcefile
  12.  *
  13.  *  NOTE: must handle mnemonic extensions and expression decode/compare.
  14.  */
  15.  
  16. #include "asm.h"
  17.  
  18. void outlistfile ARGS((char *));
  19. char *cleanup ARGS((ubyte *));
  20. uword hash1 ARGS((ubyte *));
  21.  
  22. #define MAXLINE 256
  23. #define ISEGNAME    "code"
  24.  
  25. uword _fmode = 0;    /*  was trying to port to 16 bit IBM-PC lattice C */
  26.             /*  but failed    */
  27.  
  28. ubyte    Disable_me;
  29. ubyte    StopAtEnd = 0;
  30. ubyte    *Extstr;
  31.  
  32. void
  33. main(ac, av)
  34. int ac;
  35. char *av[];
  36. {
  37.     ubyte buf[MAXLINE];
  38.     uword pass, i;
  39.     register MNE *mne;
  40.     register ulong oldredo = -1;
  41.     register ulong oldwhy = 0;
  42.     register ulong oldeval = 0;
  43.  
  44.     addhashtable(Ops);
  45.     pass = 1;
  46.  
  47.     if (ac < 2) {
  48. fail:
  49.     puts("DASM V2.12, high level Macro Assembler");
  50.     puts("(C)Copyright 1988 by Matthew Dillon, All Rights Reserved");
  51.     puts("redistributable for non-profit only");
  52.     puts("");
  53.     puts("DASM sourcefile [options]");
  54.     puts(" -f#      output format");
  55.     puts(" -oname   output file");
  56.     puts(" -lname   list file");
  57.     puts(" -sname   symbol dump");
  58.     puts(" -v#      verboseness");
  59.     puts(" -Dname=exp   define label");
  60.     exit(1);
  61.     }
  62.     puts("DASM V2.12, (c)Copyright 1988 Matthew Dillon, All Rights Reserved");
  63.     puts("Warning: The meaning of <exp & >exp has been reversed in this release");
  64.     for (i = 2; i < ac; ++i) {
  65.     if (av[i][0] == '-') {
  66.         register ubyte *str = (ubyte *)av[i]+2;
  67.         switch(av[i][1]) {
  68.         case 'd':
  69.         Xdebug = atoi(str);
  70.         printf("Xdebug = %ld\n", Xdebug);
  71.         break;
  72.         case 'D':
  73.         while (*str && *str != '=')
  74.             ++str;
  75.         if (*str == '=') {
  76.             *str = 0;
  77.             ++str;
  78.         } else {
  79.             str = (ubyte *)"0";
  80.         }
  81.         Av[0] = (ubyte *)(av[i]+2);
  82.         v_set(str, NULL);
  83.         break;
  84.         case 'f':   /*  F_format    */
  85.         F_format = atoi(str);
  86.         if (F_format < 1 || F_format > 3)
  87.             panic("Illegal format specification");
  88.         break;
  89.         case 'o':   /*  F_outfile   */
  90.         F_outfile = (char *)str;
  91. nofile:
  92.         if (*str == 0)
  93.             panic("need file name for specified option");
  94.         break;
  95.         case 'l':   /*  F_listfile  */
  96.         F_listfile = (char *)str;
  97.         goto nofile;
  98.         case 's':   /*  F_symfile   */
  99.         F_symfile = (char *)str;
  100.         goto nofile;
  101.         case 'v':   /*  F_verbose   */
  102.         F_verbose = atoi(str);
  103.         break;
  104.         case 't':   /*  F_temppath  */
  105.         F_temppath = (char *)str;
  106.         break;
  107.         default:
  108.         goto fail;
  109.         }
  110.         continue;
  111.     }
  112.     goto fail;
  113.     }
  114.  
  115.     /*    INITIAL SEGMENT */
  116.  
  117.     {
  118.     register SEGMENT *seg = (SEGMENT *)permalloc(sizeof(SEGMENT));
  119.     seg->name = (ubyte *)strcpy(permalloc(sizeof(ISEGNAME)), ISEGNAME);
  120.     seg->flags= seg->rflags = seg->initflags = seg->initrflags = SF_UNKNOWN;
  121.     Csegment = Seglist = seg;
  122.     }
  123.     /*    TOP LEVEL IF    */
  124.     {
  125.     register IFSTACK *ifs = (IFSTACK *)zmalloc(sizeof(IFSTACK));
  126.     ifs->file = NULL;
  127.     ifs->flags = IFF_BASE;
  128.     ifs->acctrue = 1;
  129.     ifs->true  = 1;
  130.     Ifstack = ifs;
  131.     }
  132. nextpass:
  133.     Localindex = 0;
  134.     _fmode = 0x8000;
  135.     FI_temp = fopen(F_outfile, "w");
  136.     _fmode = 0;
  137.     Fisclear = 1;
  138.     CheckSum = 0;
  139.     if (FI_temp == NULL) {
  140.     printf("unable to [re]open '%s'\n", F_outfile);
  141.     exit(1);
  142.     }
  143.     if (F_listfile) {
  144.     FI_listfile = fopen(F_listfile, "w");
  145.     if (FI_listfile == NULL) {
  146.         printf("unable to [re]open '%s'\n", F_listfile);
  147.         exit(1);
  148.     }
  149.     }
  150.     pushinclude(av[1]);
  151.     while (Incfile) {
  152.     for (;;) {
  153.         char *comment;
  154.         if (Incfile->flags & INF_MACRO) {
  155.         if (Incfile->strlist == NULL) {
  156.             Av[0] = (ubyte *)"";
  157.             v_mexit(NULL,NULL);
  158.             continue;
  159.         }
  160.         strcpy(buf, Incfile->strlist->buf);
  161.         Incfile->strlist = Incfile->strlist->next;
  162.         } else {
  163.         if (fgets(buf, MAXLINE, Incfile->fi) == NULL)
  164.             break;
  165.         }
  166.         if (Xdebug)
  167.         printf("%08lx %s\n", Incfile, buf);
  168.         comment = cleanup(buf);
  169.         if (Xdebug)
  170.         printf("ok1 "), fflush(stdout);
  171.         ++Incfile->lineno;
  172.         parse(buf);
  173.         if (Xdebug)
  174.         printf("ok2 "), fflush(stdout);
  175.         if (Av[1][0]) {
  176.         findext(Av[1]);
  177.         if (mne = findmne(Av[1])) {
  178.             if ((mne->flags & MF_IF) || (Ifstack->true && Ifstack->acctrue))
  179.             (*mne->vect)(Av[2], mne);
  180.         } else {
  181.             if (Ifstack->true && Ifstack->acctrue) {
  182.             printf("unknown mnemonic: '%s'\n", Av[1]);
  183.             asmerr(4,0);
  184.             }
  185.         }
  186.         } else {
  187.         if (Ifstack->true && Ifstack->acctrue)
  188.             programlabel();
  189.         }
  190.         if (Xdebug)
  191.         printf("ok3 "), fflush(stdout);
  192.         if (F_listfile && ListMode)
  193.         outlistfile(comment);
  194.     }
  195.     while (Reploop && Reploop->file == Incfile)
  196.         rmnode((ulong **)&Reploop, sizeof(REPLOOP));
  197.     while (Ifstack->file == Incfile)
  198.         rmnode((ulong **)&Ifstack, sizeof(IFSTACK));
  199.     fclose(Incfile->fi);
  200.     free(Incfile->name);
  201.     --Inclevel;
  202.     rmnode((ulong **)&Incfile, sizeof(INCFILE));
  203.     if (Incfile) {
  204.         /*
  205.         if (F_verbose > 1)
  206.         printf("back to: %s\n", Incfile->name);
  207.         */
  208.         if (F_listfile)
  209.         fprintf(FI_listfile, "------- FILE %s\n", Incfile->name);
  210.     }
  211.     }
  212.     if (F_verbose >= 1) {
  213.     SEGMENT *seg;
  214.     char *bss;
  215.  
  216.     puts("");
  217.     printf("END OF PASS: %d\n", pass);
  218.     puts("Segment---     init-pc  init-rpc finl-pc  finl-rpc");
  219.     for (seg = Seglist; seg; seg = seg->next) {
  220.         bss = (seg->flags & SF_BSS) ? "[u]" : "   ";
  221.         printf("%10s %3s ", seg->name, bss);
  222.         printf("%s %s ", sftos(seg->initorg, seg->initflags), sftos(seg->initrorg, seg->initrflags));
  223.         printf("%s %s\n", sftos(seg->org, seg->flags), sftos(seg->rorg, seg->rflags));
  224.     }
  225.     printf("Reasons: %4ld,%4ld   Reasoncode: %08lx\n", Redo, Redo_eval, Redo_why);
  226.     }
  227.     if (F_verbose >= 3) {
  228.     SYMBOL *sym;
  229.     short i;
  230.     short j = 0;
  231.  
  232.     if (F_verbose == 3)
  233.         puts("SYMBOLIST:  (Unresolved symbols only)");
  234.     else
  235.         puts("SYMBOLIST");
  236.     for (i = 0; i < SHASHSIZE; ++i) {
  237.         for (sym = SHash[i]; sym; sym = sym->next) {
  238.         if (F_verbose > 3 || (sym->flags & SYM_UNKNOWN)) {
  239.             printf("%10s %s\n", sym->name, sftos(sym->value, sym->flags));
  240.             j = 1;
  241.         }
  242.         }
  243.     }
  244.     if (j == 0)
  245.         puts("NO SYMBOLS");
  246.     else
  247.         puts("ENDSYMBOLIST");
  248.     }
  249.     closegenerate();
  250.     fclose(FI_temp);
  251.     if (FI_listfile)
  252.     fclose(FI_listfile);
  253.     if (Redo) {
  254.     if (Redo == oldredo && Redo_why == oldwhy && Redo_eval == oldeval) {
  255.         puts("Error: source is not resolvable.");
  256.         if (F_verbose < 2)
  257.         puts("re-run with verbose option 2 or higher to determine problem");
  258.         exit(1);
  259.     }
  260.     oldredo = Redo;
  261.     oldwhy = Redo_why;
  262.     oldeval = Redo_eval;
  263.     Redo = 0;
  264.     Redo_why = 0;
  265.     Redo_eval = 0;
  266.     ++pass;
  267.     if (StopAtEnd) {
  268.         printf("Unrecoverable error in pass, aborting assembly!\n");
  269.     } else if (pass > 10) {
  270.         printf("More than 10 passes, something *must* be wrong!\n");
  271.         exit(1);
  272.     } else {
  273.         clearrefs();
  274.         clearsegs();
  275.         goto nextpass;
  276.     }
  277.     }
  278.     if (F_symfile) {
  279.     FILE *fi = fopen(F_symfile, "w");
  280.     if (fi) {
  281.         register SYMBOL *sym;
  282.         puts("dumping symbols...");
  283.         for (i = 0; i < SHASHSIZE; ++i) {
  284.         for (sym = SHash[i]; sym; sym = sym->next) {
  285.             fprintf(fi, "%-15s %s", sym->name, sftos(sym->value, sym->flags));
  286.             if (sym->flags & SYM_STRING)
  287.             fprintf(fi, " \"%s\"", sym->string);
  288.             putc('\n', fi);
  289.         }
  290.         }
  291.         fclose(fi);
  292.     } else {
  293.         printf("unable to open symbol dump file '%s'\n", F_symfile);
  294.     }
  295.     }
  296. }
  297.  
  298. static void
  299. outlistfile(comment)
  300. char *comment;
  301. {
  302.     extern ubyte Gen[];
  303.     extern short Glen;
  304.     char c = (Pflags & SF_BSS) ? 'U' : ' ';
  305.     static char buf1[MAXLINE+32];
  306.     static char buf2[MAXLINE+32];
  307.     ubyte *ptr = Extstr;
  308.     char *dot = "";
  309.     register int i, j;
  310.  
  311.     if (ptr)
  312.     dot = ".";
  313.     else
  314.     ptr = (ubyte *)"";
  315.  
  316.     sprintf(buf1, "%6ld %c%s", Incfile->lineno, c, sftos(Plab, Pflags & 7));
  317.     j = strlen(buf1);
  318.     for (i = 0; i < Glen && i < 4; ++i, j += 3)
  319.     sprintf(buf1+j, "%02x ", Gen[i]);
  320.     if (i < Glen && i == 4)
  321.     buf1[j-1] = '*';
  322.     for (; i < 4; ++i) {
  323.     buf1[j] = buf1[j+1] = buf1[j+2] = ' ';
  324.     j += 3;
  325.     }
  326.     sprintf(buf1+j, "%-10s  %s%s%s\011%s\n", Av[0], Av[1], dot, ptr, Av[2]);
  327.     if (comment[0]) { /*  tab and comment */
  328.     j = strlen(buf1) - 1;
  329.     sprintf(buf1+j, "\011;%s", comment);
  330.     }
  331.     fwrite(buf2, tabit(buf1,buf2), 1, FI_listfile);
  332.     Glen = 0;
  333.     Extstr = NULL;
  334. }
  335.  
  336. int
  337. tabit(buf1, buf2)
  338. char *buf1, *buf2;
  339. {
  340.     register char *bp, *ptr;
  341.     register short j, k;
  342.  
  343.     bp = buf2;
  344.     ptr= buf1;
  345.     for (j = 0; *ptr; ++ptr, ++bp, j = (j+1)&7) {
  346.     *bp = *ptr;
  347.     if (*ptr == 9)
  348.         j = 0;
  349.     if (j == 7 && *bp == ' ' && *(bp-1) == ' ') {
  350.         k = j;
  351.         while (k-- >= 0 && *bp == ' ')
  352.         --bp;
  353.         *++bp = 9;
  354.     }
  355.     }
  356.     while (bp != buf2 && bp[-1] == ' ' || bp[-1] == 9)
  357.     --bp;
  358.     *bp = *ptr;
  359.     return((int)(bp - buf2));
  360. }
  361.  
  362.  
  363. ubyte *
  364. sftos(val, flags)
  365. long val;
  366. int flags;
  367. {
  368.     static char buf[64];
  369.     static char c;
  370.     register char *ptr = (c) ? buf : buf + 32;
  371.  
  372.     c = 1 - c;
  373.     sprintf(ptr, "%04lx", val);
  374.     if (flags & SYM_UNKNOWN)
  375.     strcpy(ptr, "????");
  376.     if (flags & SYM_STRING)
  377.     strcpy(ptr, "str ");
  378.     if (flags & SYM_MACRO)
  379.     strcpy(ptr, "eqm ");
  380.     strcpy(ptr+4, "    ");
  381.     if (flags & (SYM_MASREF|SYM_SET)) {
  382.     ptr[4] = '(';
  383.     ptr[7] = ')';
  384.     }
  385.     if (flags & (SYM_MASREF))
  386.     ptr[5] = 'r';
  387.     if (flags & (SYM_SET))
  388.     ptr[6] = 's';
  389.     return((ubyte *)ptr);
  390. }
  391.  
  392. void
  393. clearsegs()
  394. {
  395.     register SEGMENT *seg;
  396.  
  397.     for (seg = Seglist; seg; seg = seg->next) {
  398.     seg->flags = (seg->flags & SF_BSS) | SF_UNKNOWN;
  399.     seg->rflags= seg->initflags = seg->initrflags = SF_UNKNOWN;
  400.     }
  401. }
  402.  
  403. void
  404. clearrefs()
  405. {
  406.     register SYMBOL *sym;
  407.     register short i;
  408.  
  409.     for (i = 0; i < SHASHSIZE; ++i)
  410.     for (sym = SHash[i]; sym; sym = sym->next)
  411.         sym->flags &= ~SYM_REF;
  412. }
  413.  
  414. static
  415. char *
  416. cleanup(buf)
  417. register ubyte *buf;
  418. {
  419.     register ubyte *str;
  420.     register STRLIST *strlist;
  421.     register short arg, add;
  422.     char *comment = "";
  423.  
  424.     for (str = buf; *str; ++str) {
  425.     switch(*str) {
  426.     case ';':
  427.         comment = (char *)str + 1;
  428.         /*    FALL THROUGH    */
  429.     case '\r':
  430.     case '\n':
  431.         goto br2;
  432.     case TAB:
  433.         *str = ' ';
  434.         break;
  435.     case '\'':
  436.         ++str;
  437.         if (*str == TAB)
  438.         *str = ' ';
  439.         if (*str == '\n' || *str == 0) {
  440.         str[0] = ' ';
  441.         str[1] = 0;
  442.         }
  443.         if (str[0] == ' ')
  444.         str[0] = 0x80;
  445.         break;
  446.     case '\"':
  447.         ++str;
  448.         while (*str && *str != '\"') {
  449.         if (*str == ' ')
  450.             *str = 0x80;
  451.         ++str;
  452.         }
  453.         if (*str != '\"') {
  454.         asmerr(0,0);
  455.         --str;
  456.         }
  457.         break;
  458.     case '{':
  459.         if (Disable_me)
  460.         break;
  461.         if (Xdebug)
  462.         printf("macro tail: '%s'\n", str);
  463.         arg = atoi(str+1);
  464.         for (add = 0; *str && *str != '}'; ++str)
  465.         --add;
  466.         if (*str != '}') {
  467.         puts("end brace required");
  468.         --str;
  469.         break;
  470.         }
  471.         --add;
  472.         ++str;
  473.         if (Xdebug)
  474.         printf("add/str: %d '%s'\n", add, str);
  475.         for (strlist = Incfile->args; arg && strlist;) {
  476.         --arg;
  477.         strlist = strlist->next;
  478.         }
  479.         if (strlist) {
  480.         add += strlen(strlist->buf);
  481.         if (Xdebug)
  482.             printf("strlist: '%s' %d\n", strlist->buf, strlen(strlist->buf));
  483.         if (str + add + strlen(str) + 1 > buf + MAXLINE) {
  484.             if (Xdebug)
  485.             printf("str %8ld buf %8ld (add/strlen(str)): %d %ld\n", str, buf, add, strlen(str));
  486.             panic("failure1");
  487.         }
  488.         BMov(str, str + add, strlen(str)+1);
  489.         str += add;
  490.         if (str - strlen(strlist->buf) < buf)
  491.             panic("failure2");
  492.         BMov(strlist->buf, str - strlen(strlist->buf), strlen(strlist->buf));
  493.         str -= strlen(strlist->buf);
  494.         if (str < buf || str >= buf + MAXLINE)
  495.             panic("failure 3");
  496.         --str;    /*  for loop increments string    */
  497.         } else {
  498.         asmerr(7,0);
  499.         goto br2;
  500.         }
  501.         break;
  502.     }
  503.     }
  504. br2:
  505.     while(str != buf && *(str-1) == ' ')
  506.     --str;
  507.     *str = 0;
  508.     return(comment);
  509. }
  510.  
  511. void
  512. panic(str)
  513. char *str;
  514. {
  515.     puts(str);
  516.     exit(1);
  517. }
  518.  
  519. /*
  520.  *  .dir    direct            x
  521.  *  .ext    extended            x
  522.  *  .r        relative            x
  523.  *  .x        index, no offset        x
  524.  *  .x8     index, byte offset        x
  525.  *  .x16    index, word offset        x
  526.  *  .bit    bit set/clr
  527.  *  .bbr    bit and branch
  528.  *  .imp    implied (inherent)      x
  529.  *  .b                    x
  530.  *  .w                    x
  531.  *  .l                    x
  532.  *  .u                    x
  533.  */
  534.  
  535.  
  536. void
  537. findext(str)
  538. register ubyte *str;
  539. {
  540.     Mnext = -1;
  541.     Extstr = NULL;
  542.     while (*str && *str != '.')
  543.     ++str;
  544.     if (*str) {
  545.     *str = 0;
  546.     ++str;
  547.     Extstr = str;
  548.     switch(str[0]|0x20) {
  549.     case '0':
  550.     case 'i':
  551.         Mnext = AM_IMP;
  552.         switch(str[1]|0x20) {
  553.         case 'x':
  554.         Mnext = AM_0X;
  555.         break;
  556.         case 'y':
  557.         Mnext = AM_0Y;
  558.         break;
  559.         case 'n':
  560.         Mnext = AM_INDWORD;
  561.         break;
  562.         }
  563.         return;
  564.     case 'd':
  565.     case 'b':
  566.     case 'z':
  567.         switch(str[1]|0x20) {
  568.         case 'x':
  569.         Mnext = AM_BYTEADRX;
  570.         break;
  571.         case 'y':
  572.         Mnext = AM_BYTEADRY;
  573.         break;
  574.         case 'i':
  575.         Mnext = AM_BITMOD;
  576.         break;
  577.         case 'b':
  578.         Mnext = AM_BITBRAMOD;
  579.         break;
  580.         default:
  581.         Mnext = AM_BYTEADR;
  582.         break;
  583.         }
  584.         return;
  585.     case 'e':
  586.     case 'w':
  587.     case 'a':
  588.         switch(str[1]|0x20) {
  589.         case 'x':
  590.         Mnext = AM_WORDADRX;
  591.         break;
  592.         case 'y':
  593.         Mnext = AM_WORDADRY;
  594.         break;
  595.         default:
  596.         Mnext = AM_WORDADR;
  597.         break;
  598.         }
  599.         return;
  600.     case 'l':
  601.         Mnext = AM_LONG;
  602.         return;
  603.     case 'r':
  604.         Mnext = AM_REL;
  605.         return;
  606.     case 'u':
  607.         Mnext = AM_BSS;
  608.         return;
  609.     }
  610.     }
  611. }
  612.  
  613. /*
  614.  *  bytes arg will eventually be used to implement a linked list of free
  615.  *  nodes.
  616.  */
  617.  
  618. void
  619. rmnode(base, bytes)
  620. ulong **base;
  621. int bytes;
  622. {
  623.     ulong *node;
  624.  
  625.     if (node = *base) {
  626.     *base = *(ulong **)node;
  627.     free(node);
  628.     }
  629. }
  630.  
  631. /*
  632.  *  Parse into three arguments: Av[0], Av[1], Av[2]
  633.  */
  634.  
  635. void
  636. parse(buf)
  637. register ubyte *buf;
  638. {
  639.     register short i, j;
  640.  
  641.     i = j = 0;
  642.     Av[0] = Avbuf;
  643.     while (buf[i] && buf[i] != ' ') {
  644.     if (buf[i] == 0x80)
  645.         buf[i] = ' ';
  646.     Avbuf[j++] = buf[i++];
  647.     }
  648.     Avbuf[j++] = 0;
  649.     while (buf[i] == ' ')
  650.     ++i;
  651.     Av[1] = Avbuf + j;
  652.     while (buf[i] && buf[i] != ' ') {
  653.     if (buf[i] == 0x80)
  654.         buf[i] = ' ';
  655.     Avbuf[j++] = buf[i++];
  656.     }
  657.     Avbuf[j++] = 0;
  658.     while (buf[i] == ' ')
  659.     ++i;
  660.     Av[2] = Avbuf + j;
  661.     while (buf[i]) {
  662.     if (buf[i] == ' ') {
  663.         while(buf[i+1] == ' ')
  664.         ++i;
  665.     }
  666.     if (buf[i] == 0x80)
  667.         buf[i] = ' ';
  668.     Avbuf[j++] = buf[i++];
  669.     }
  670.     Avbuf[j] = 0;
  671. }
  672.  
  673.  
  674.  
  675. MNE *
  676. findmne(str)
  677. register ubyte *str;
  678. {
  679.     register uword i;
  680.     register ubyte c;
  681.     register MNE *mne;
  682.     ubyte buf[128];
  683.  
  684.     for (i = 0; c = str[i]; ++i) {
  685.     if (c >= 'A' && c <= 'Z')
  686.         c += 'a' - 'A';
  687.     buf[i] = c;
  688.     }
  689.     buf[i] = 0;
  690.     for (mne = MHash[hash1(buf)]; mne; mne = mne->next) {
  691.     if (strcmp(buf, mne->name) == 0)
  692.         break;
  693.     }
  694.     return(mne);
  695. }
  696.  
  697. void
  698. v_macro(str, mnee)
  699. char *str;
  700. MNE *mnee;
  701. {
  702.     STRLIST *base;
  703.     ubyte defined = 0;
  704.     register STRLIST **slp, *sl;
  705.     register MACRO *mac;
  706.     register MNE   *mne;
  707.     register uword i;
  708.     ubyte buf[MAXLINE];
  709.     ubyte skipit = !(Ifstack->true && Ifstack->acctrue);
  710.  
  711.     strlower(str);
  712.     if (skipit) {
  713.     defined = 1;
  714.     } else {
  715.     defined = (findmne(str) != NULL);
  716.     if (F_listfile && ListMode)
  717.         outlistfile("");
  718.     }
  719.     if (!defined) {
  720.     base = NULL;
  721.     slp = &base;
  722.     mac = (MACRO *)permalloc(sizeof(MACRO));
  723.     i = hash1(str);
  724.     mac->next = (MACRO *)MHash[i];
  725.     mac->vect = v_execmac;
  726.     mac->name = (ubyte *)strcpy(permalloc(strlen(str)+1), str);
  727.     mac->flags = MF_MACRO;
  728.     MHash[i] = (MNE *)mac;
  729.     }
  730.     while (fgets(buf, MAXLINE, Incfile->fi)) {
  731.     char *comment;
  732.  
  733.     if (Xdebug)
  734.         printf("%08lx %s\n", Incfile, buf);
  735.     ++Incfile->lineno;
  736.     Disable_me = 1;
  737.     comment = cleanup(buf);
  738.     Disable_me = 0;
  739.     if (parse(buf), Av[1][0]) {
  740.         findext(Av[1]);
  741.         mne = findmne(Av[1]);
  742.         if (mne->flags & MF_ENDM) {
  743.         if (!defined)
  744.             mac->strlist = base;
  745.         return;
  746.         }
  747.     }
  748.     if (Xdebug)
  749.         printf("ok1"), fflush(stdout);
  750.     if (!skipit && F_listfile && ListMode)
  751.         outlistfile(comment);
  752.     if (Xdebug)
  753.         printf("ok2"), fflush(stdout);
  754.     if (!defined) {
  755.         sl = (STRLIST *)permalloc(5+strlen(buf));
  756.         strcpy(sl->buf, buf);
  757.         *slp = sl;
  758.         slp = &sl->next;
  759.     }
  760.     if (Xdebug)
  761.         printf("ok3\n"), fflush(stdout);
  762.     }
  763.     asmerr(8,1);
  764. }
  765.  
  766. void
  767. addhashtable(mne)
  768. MNE *mne;
  769. {
  770.     register uword i, j;
  771.     uword opcode[NUMOC];
  772.  
  773.     for (; mne->vect; ++mne) {
  774.     BMov(mne->opcode, opcode, sizeof(mne->opcode));
  775.     for (i = j = 0; i < NUMOC; ++i) {
  776.         mne->opcode[i] = 0;     /* not really needed */
  777.         if (mne->okmask & (1L << i))
  778.         mne->opcode[i] = opcode[j++];
  779.     }
  780.     i = hash1(mne->name);
  781.     mne->next = MHash[i];
  782.     MHash[i] = mne;
  783.     }
  784. }
  785.  
  786. static uword
  787. hash1(str)
  788. register ubyte *str;
  789. {
  790.     register uword result = 0;
  791.  
  792.     while (*str)
  793.     result = (result << 2) ^ *str++;
  794.     return((uword)(result & MHASHAND));
  795. }
  796.  
  797. void
  798. pushinclude(str)
  799. char *str;
  800. {
  801.     register INCFILE *inf;
  802.     register FILE *fi;
  803.  
  804.     if (fi = fopen(str, "r")) {
  805.     if (F_verbose > 1) {
  806. #ifdef IBM
  807.         printf(" Include: %s\n", str);
  808. #else
  809.         printf("%.*sInclude: %s\n", Inclevel*4, "", str);
  810. #endif
  811.     }
  812.     ++Inclevel;
  813.     if (F_listfile)
  814.         fprintf(FI_listfile, "------- FILE %s\n", str);
  815.     inf = (INCFILE *)zmalloc(sizeof(INCFILE));
  816.     inf->next   = Incfile;
  817.     inf->name   = (ubyte *)strcpy(malloc(strlen(str)+1), str);
  818.     inf->fi     = fi;
  819.     inf->lineno = 0;
  820.     Incfile = inf;
  821.     return;
  822.     }
  823.     printf("unable to open %s\n", str);
  824. }
  825.  
  826. char Stopend[] = {
  827.     1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,0,0,1,1
  828. };
  829.  
  830. char *Errors[] = {
  831.     "Syntax Error",
  832.     "Expression table overflow",
  833.     "Unbalanced Braces []",
  834.     "Division by zero",
  835.     "Unknown Mnemonic",
  836.     "Illegal Addressing mode",
  837.     "Illegal forced Addressing mode",   /*  nu  */
  838.     "Not enough args passed to Macro",
  839.     "Premature EOF",
  840.     "Illegal character",
  841.     "Branch out of range",
  842.     "ERR pseudo-op encountered",
  843.     "Origin Reverse-indexed",           /*  12  */
  844.     "EQU: Value mismatch",
  845.     "Address must be <$100",            /*  nu  */
  846.     "Illegal bit specification",
  847.     "Not enough args",                  /*  16  */
  848.     "Label Mismatch",                   /*  17  */
  849.     "Value Undefined",
  850.     "Illegal Forced Address mode",      /*  19  */
  851.     "Processor not supported",          /*  20  */
  852.     NULL
  853. };
  854.  
  855. void
  856. asmerr(err, abort)
  857. short err, abort;
  858. {
  859.     ubyte *str;
  860.     INCFILE *incfile;
  861.  
  862.     if (Stopend[err])
  863.     StopAtEnd = 1;
  864.     for (incfile = Incfile; incfile->flags & INF_MACRO; incfile=incfile->next);
  865.     str = (ubyte *)Errors[err];
  866.     if (F_listfile)
  867.     fprintf(FI_listfile, "*line %4ld %-10s %s\n", incfile->lineno, incfile->name, str);
  868.     printf("line %4ld %-10s %s\n", incfile->lineno, incfile->name, str);
  869.     if (abort) {
  870.     puts("Aborting assembly");
  871.     if (F_listfile)
  872.         fputs("Aborting assembly\n", FI_listfile);
  873.     exit(1);
  874.     }
  875. }
  876.  
  877. ubyte *
  878. zmalloc(bytes)
  879. int bytes;
  880. {
  881.     ubyte *ptr = malloc(bytes);
  882.     if (ptr) {
  883.     BZero(ptr, bytes);
  884.     return(ptr);
  885.     }
  886.     panic("unable to malloc");
  887. }
  888.  
  889. ubyte *
  890. permalloc(bytes)
  891. int bytes;
  892. {
  893.     static ubyte *buf;
  894.     static int left;
  895.     ubyte *ptr;
  896.  
  897.     bytes = (bytes + 1) & ~1;
  898.     if (bytes > left) {
  899.     if ((buf = malloc(ALLOCSIZE)) == NULL)
  900.         panic("unable to malloc");
  901.     BZero(buf, ALLOCSIZE);
  902.     left = ALLOCSIZE;
  903.     if (bytes > left)
  904.         panic("software error");
  905.     }
  906.     ptr = buf;
  907.     buf += bytes;
  908.     left -= bytes;
  909.     return(ptr);
  910. }
  911.  
  912. ubyte *
  913. strlower(str)
  914. ubyte *str;
  915. {
  916.     register ubyte c;
  917.     register ubyte *ptr;
  918.  
  919.     for (ptr = str; c = *ptr; ++ptr) {
  920.     if (c >= 'A' && c <= 'Z')
  921.         *ptr = c | 0x20;
  922.     }
  923.     return(str);
  924. }
  925.  
  926.  
  927. #ifdef UNIX
  928. xbset(s,n,c)
  929. register ubyte *s;
  930. register ulong n;
  931. register ubyte c;
  932. {
  933.     while (n--)
  934.     *s++ = c;
  935. }
  936. #endif
  937.  
  938. #ifdef IBM
  939. BCmp(s,d,n)
  940. ubyte *s, *d;
  941. uword n;
  942. {
  943.     uword i;
  944.     for (i = 0; i < n; ++i) {
  945.     if (s[i] != d[i])
  946.         return(1);
  947.     }
  948.     return(0);
  949. }
  950.  
  951. #endif
  952.  
  953.  
  954.  
  955.