home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / asmutl / smmaclnk.ark / MAC.C < prev    next >
Text File  |  1987-09-10  |  11KB  |  394 lines

  1. /*
  2. ** MAC.C -- Small-Mac Assembler -- Part 1: Mainline and Macro Functions
  3. **
  4. **    Copyright 1985 J. E. Hendrix
  5. **
  6. ** usage: MAC [-L] [-NM] [-P] [-S#] [object] source...
  7. **
  8. ** -L        Generate an assembly listing on the standard output file.
  9. **
  10. ** -NM        No macro processing.  This speeds up the assembler somewhat.
  11. **        Macro processing is NOT needed for Small-C 2.1 output files.
  12. **
  13. ** -P        Pause on errors waiting for an operator response of CR.
  14. **
  15. ** -S#        Set symble table size to accept # symbols.
  16. **
  17. ** object    Name of the object file to be output.  It must have a REL
  18. **        extension to be recognized as an output file. A drive
  19. **        specifier is allowed.  If not specified, the object code
  20. **        will go into a file (on the default drive) bearing the same
  21. **        name as the first source file, but with a REL extension.
  22. ** source...    Names of the source files to be assembled.  The default, and
  23. **        only allowed, extension is MAC.  A drive specifier is allowed.
  24. **        The named files will be assembled as one file concatenated
  25. **        in the order given.
  26. **
  27. **        NOTE: The module name in the REL file will be taken from
  28. **        the first 6 characters of the object filename.
  29. */
  30. #include <stdio.h>
  31. #include "notice.h"
  32. #include "mac.h"
  33. #include "rel.h"
  34. #include "mit.h"
  35. #define NOCCARGC
  36.  
  37. /*
  38. ** symbol table
  39. */
  40. int
  41.   stmax = STMAX,        /* maximum symbols */
  42.   stn,                /* number of symbols loades */
  43.  *stp;                /* symbol table pointer array */
  44. char
  45.  *st,                /* symble table buffer */
  46.  *stend,            /* end of symbol tBLE */
  47.  *stptr,            /* st entry pointer */
  48.   stsym[MAXLAB+1];        /* temporRY SYMBOL SPACE */
  49.  
  50. /*
  51. ** macro definition table
  52. */
  53. char
  54.  *mt,                /* macro tBLE BUFFER */
  55.  *mtprev,            /* previous mt entry */
  56.  *mtnext,            /* next available mt byte */
  57.  *mtend,            /* end of macro table */
  58.  *mtptr;            /* mt entry pointer */
  59.  
  60. int
  61.   pass = 1,            /* which pass? */
  62.   badsym,            /* bad symbol? */
  63.   gotep,            /* have an entry point? */
  64.   gotxr,            /* have an external reference? */
  65.   gotlabel,            /* have a label? */
  66.   gotnam,            /* have a name? */
  67.   eom,                /* end of module? */
  68.   endv,                /* END value? */
  69.   endt,                /* END type? */
  70.   err,                /* error? */
  71.   lerr,                /* line error flages */
  72.   loc,                /* location counter */
  73.   lin,                /* line counter */
  74.   srcfd,            /* source file fd */
  75.   list,                /* generate alisting? */
  76.   lline,            /* listing inene, force 1st page heading */
  77.   part1,            /* part one of listing line printed? */
  78.   ccnt,                /* count of code characters printed */
  79.   lpage,            /* listing page */
  80.   pause,            /* pause on errors? */
  81.   looks,            /* number of looks to find instruction */
  82.   macros = YES,            /* macro processing? */
  83.   mlnext,            /* next macro label to assign */
  84.   mlnbr[10],            /* macro label numbers */
  85.   mpptr[10],            /* macro parameter pointers */
  86.   defmode,            /* macro definition mode */
  87.   expmode;            /* macro expansion mode */
  88.  
  89. char
  90.  *ep,                /* expression pointer */
  91.  *lp,                /* line pointer */
  92.   line[MAXLINE],        /* source line */
  93.  *prior,            /* prior ext ref in chain */
  94.   srcfn[MAXFN+4],        /* source filename */
  95.   objfn[MAXFN+4];        /* object filename */
  96.  
  97. main(argc, argv) int argc, *argv; {
  98.   fputs("Small-Mac Assembler, ", stderr); fputs(VERSION, stderr);
  99.   fputs(CRIGHT1, stderr);
  100.   getsw(argc, argv);        /* get command line options */
  101.   pass1(argc, argv);        /* build symbol table */
  102.   pass2(argc, argv);        /* generate object code */
  103.   if(err) abort(7);        /* sound the alarm */
  104.   }
  105.  
  106. /*
  107. ** pass one
  108. */
  109. pass1(argc, argv) int argc, *argv; {
  110.   int max;
  111.   st = calloc(STBUFSZ, 1);    /* allocate zeroed symbol table */
  112.   stp = calloc(stmax, INTSZ);
  113.   stend = st + STBUFSZ;        /* remember end of table */
  114.   max = avail(YES);        /* how much available? */
  115.   max -= STACK + (MAXOPEN * OHDOPEN);    /* calculate how much */
  116.   mt = mtnext = calloc(max, 1);    /* allocate space */
  117.   mtend = mt + max - MAXLINE;    /* note end of macro buffer */
  118.   dopass(argc, argv);        /* do pass 1 */
  119.   }
  120.  
  121. /*
  122. ** pass two
  123. */
  124. pass2(argc, argv) int argc, *argv; {
  125.   int i;
  126.   outrel = open(objfn, "w");    /* open object file */
  127.   putname();            /* declare module name */
  128.   putent();            /* declare entry points */
  129.   putsz();            /* declare program size */
  130.   pass = 2;            /* signal pass 2 */
  131.   dopass(argc, argv);        /* do pass 2 */
  132.   putexs();            /* declare ep and xr symbols */
  133.   putend();            /* declare end of program */
  134.   if(ferror(outrel)) err = YES;
  135.   close(outrel);        /* close object file */
  136.   }
  137.  
  138. /*
  139. ** process passes 1 and 2
  140. */
  141. dopass(argc, argv) int argc, *argv; {
  142.   int mop;
  143.   int i;
  144.   mlnext = lpage = i = lin = loc = 0;    /* reset everything */
  145.   lline = 100;                /* force page heading */
  146.  
  147.   while(getarg(++i, srcfn, MAXFN, argc, argv) != EOF) {
  148.     if(srcfn[0] == '-') continue;
  149.     if(extend(srcfn, SRCEXT, OBJEXT)) continue;
  150.     srcfd = open(srcfn, "r");    /* open source file */
  151.     eom = NO;            /* not end of module */
  152.     goto input;
  153.     while(YES) {
  154.       poll(YES);
  155.       ++lin; lerr = 0;        /* bump line counter & zero errors */
  156.       part1 = NO;        /* part 1 of line not listed */
  157.       beglin();            /* begin a listing line */
  158.       if(macros == NO) {
  159.     dolabel();        /* do label and find next field */
  160.     if(!domach()) doasm();    /* machine or assembler instr? */
  161.     }
  162.       else {
  163.     lp = line;
  164.     lp = getsym(lp, NO);
  165.     if(!(mop = macop()) && gotnam) {    /* 2nd field a token? */
  166.       lp = skip(1, line);            /* no, ttry fisrst */
  167.       mop = macop();
  168.       }
  169.     if(defmode) {        /* definition mode */
  170.       if(mop == ENDM) defmode = NO;
  171.       if(pass == 1) putmac();    /* put line in macro table */
  172.       }
  173.     else {            /* copy or expansion mode */
  174.       if(mop == CALL) {    /* enter expansion mode */
  175.         expmode = YES;
  176.         putparm();        /* savew parameters */
  177.         dolabel();        /* process label */
  178.         }
  179.       else if(mop == MACRO) {    /* enter definition mode */
  180.         defmode = YES;
  181.         if(pass == 1) newmac();    /* init new macro in table */
  182.         }
  183.       else if(mop == ENDM) {    /* leave expansion mode */
  184.         expmode = NO;
  185.         }
  186.       else {
  187.         if(expmode) replace();
  188.         dolabel();        /* do label and find next field */
  189.         if(!domach()) doasm();    /* machine or assembler instr? */
  190.         }
  191.       }
  192.     }
  193.       endline();        /* end a lising line */
  194.       if(pass == 2) gripe();    /* gripe about errors */
  195.       if(expmode) getmac();    /* fetch next macro line */
  196.       else {
  197.     input:
  198.     if(eom) break;
  199.     if(!fgets(line, MAXLINE, srcfd)) error("- Missing END");
  200.     }
  201.       }
  202.     if(defmode) {err = YES; puts("- Missing ENDM");}
  203.     close(srcfd);        /* close source file */
  204.     }
  205.   }
  206.  
  207. /*
  208. ** can line take more?
  209. */
  210. cantake(i, need) int i, need; {
  211.   return (i < (MAXLINE - 3) - need);
  212.   }
  213.  
  214. /*
  215. ** get a line from the macro buffer
  216. */
  217. getmac() {
  218.   char *cp; cp = line;
  219.   while(*cp++ = *mtptr++) ;
  220.   }
  221.  
  222. /*
  223. ** get switches from command line
  224. */
  225. getsw(argc, argv) int argc, *argv; {
  226.   char arg[MAXFN+4]; int i, j, len;
  227.   i = 0;
  228.   while(getarg(++i, arg, MAXFN, argc, argv) != EOF) {
  229.     if(arg[0] == '-') {
  230.            if(toupper(arg[1]) == 'L') list = YES;
  231.       else if(toupper(arg[1]) == 'P') pause = YES;
  232.       else if(toupper(arg[1]) == 'N' &&
  233.           toupper(arg[2]) == 'M') macros = NO;
  234.       else if(toupper(arg[1]) == 'S') {
  235.     len = utoi(arg + 2, &j);
  236.     if(len > 0 && !arg[len + 2]) stmax = j;
  237.     else usage();
  238.     }
  239.       else usage();
  240.       }
  241.     else {
  242.       if(extend(arg, OBJEXT, OBJEXT) || !*objfn) {
  243.     if(arg[1] == ':') j = 2; else j = 0;
  244.     strcpy(objfn, arg + j);
  245.     }
  246.       }
  247.     }
  248.   }
  249.  
  250. /*
  251. ** recognize macro operation
  252. */
  253. macop() {
  254.   if(fldcmp(lp, "ENDM" ) == 0) return (ENDM);
  255.   if(fldcmp(lp, "MACRO") == 0) return (MACRO);
  256.   if(!expmode && !defmode && mtfind()) return (CALL);
  257.   return (NO);
  258.   }
  259.  
  260. /*
  261. ** test for macro buffer overflow
  262. */
  263. macover(ptr) char *ptr; {
  264.   if(ptr > mtend) error("- Macro Buffer Overflow");
  265.   }
  266.  
  267. /*
  268. ** find stsym in macro table
  269. ** return true if found, else false
  270. ** leave mtptr pointing to body of desired macro
  271. */
  272. mtfind() {
  273.   if(atend(*lp) == 0) {
  274.     mtptr = mt;
  275.     do {
  276.       if(fldcmp(lp, mtptr + MTNAM) == 0) {
  277.     mtptr += MTNAM;
  278.     mtptr += strlen(mtptr) +1;
  279.     return (YES);
  280.     }
  281.       mtptr = getint(mtptr);
  282.       } while(mtptr);
  283.     }
  284.   return (NO);
  285.   }
  286.  
  287. /*
  288. ** establish new macro
  289. */
  290. newmac() {
  291.   int i; i = 0;
  292.   if(!gotnam || badsym) symerr();
  293.   else {
  294.     macover(mtnext);
  295.     if(mtprev) putint(mtprev, mtnext);
  296.     mtprev = mtnext;
  297.     putint(mtnext, 0);
  298.     mtnext += INTSZ;
  299.     while(*mtnext++ = stsym[i++]) ;
  300.     }
  301.   }
  302.  
  303. /*
  304. ** put a line in the macro buffer
  305. */
  306. putmac() {
  307.   char *cp; cp = line;
  308.   macover(mtnext);        /* will buffer take it? */
  309.   while(*mtnext++ = *cp++) ;    /* copy everything */
  310.   }
  311.  
  312. /*
  313. ** save macro call parameters in macro buffer
  314. ** and reset labels
  315. */
  316. putparm() {
  317.   int i, dlm; char *cp;
  318.   i = -1; cp = mtnext;
  319.   lp = skip(2, lp);        /* skip to parameters */
  320.   while(++i < 10) {
  321.     mlnbr[i] = 0;        /* null macro label nbr */
  322.     while(isspace(*lp)) ++lp;
  323.     if(atend(*lp) || *lp == ',') mpptr[i] = 0;
  324.     else {
  325.       macover(cp);
  326.       mpptr[i] = cp;
  327.       while(!atend(*lp) && *lp != ',') {
  328.     if(*lp == '\"' || *lp == '\'') {
  329.       dlm = *lp;
  330.       while(!atend(*++lp)) {
  331.         if(*lp == dlm && *++lp != dlm) break;
  332.         *cp++ = *lp;
  333.         }
  334.       }
  335.     else *cp++ = *lp++;
  336.     }
  337.       *cp++ = NULL;
  338.       }
  339.     if(*lp == ',') ++lp;
  340.     }
  341.   if(!atend(*lp)) parerr();
  342.   }
  343.  
  344. /*
  345. ** replace parameters
  346. */
  347. replace () {
  348.   char lin[MAXLINE]; int ndx;
  349.   char *cp, *cp2;    int i;
  350.   strcpy(lin, line); cp = lin; i = 0;
  351.   do {
  352.     if(*cp == '?') {            /* substitution marker? */
  353.       if(isdigit(*++cp)) {        /* parameter substitution */
  354.     ndx = *cp++ - '0' - 1;        /* which one? */
  355.     if(ndx < 0) ndx = 9;        /* make 0 mean 10 */
  356.     if(cp2 = mpptr[ndx]) {        /* got parameter? */
  357.       while(*cp2)            /* yes, copy it */
  358.         if(cantake(i, 1)) line[i++] = *cp2++;
  359.       }
  360.     continue;
  361.     }
  362.       }
  363.     if(*cp == '@') {            /* label substitution? */
  364.       if(cantake(i, 1)) line[i++] = '@';/* insert label prefix */
  365.       if(isdigit(*++cp)) {        /* which one? */
  366.     ndx = *cp++ - '0';
  367.     if(!mlnbr[ndx]) mlnbr[ndx] = ++mlnext;    /* need new label number? */
  368.     if(cantake(i, 5)) {
  369.       left(itou(mlnbr[ndx], line + i, 5));    /* insert label number */
  370.       while(line[i]) ++i;        /* bypass label number */
  371.       }
  372.     continue;
  373.     }
  374.       }
  375.     if(cantake(i, 1)) line[i++] = *cp++;
  376.     else {
  377.       line[i++] = '\n';
  378.       break;
  379.       }
  380.     } while(*cp);
  381.   line[i] = NULL;
  382.   }
  383.  
  384. /*
  385. ** abort with message
  386. */
  387. usage() {
  388.   error("Usage: MAC [-L] [-NM] [-P] [-S#] [object] source...");
  389.   }
  390.  NULL;
  391.   }
  392.  
  393. /*
  394. ** abort with me