home *** CD-ROM | disk | FTP | other *** search
- /*
- ** MAC.C -- Small-Mac Assembler -- Part 1: Mainline and Macro Functions
- **
- ** Copyright 1985 J. E. Hendrix
- **
- ** usage: MAC [-L] [-NM] [-P] [-S#] [object] source...
- **
- ** -L Generate an assembly listing on the standard output file.
- **
- ** -NM No macro processing. This speeds up the assembler somewhat.
- ** Macro processing is NOT needed for Small-C 2.1 output files.
- **
- ** -P Pause on errors waiting for an operator response of CR.
- **
- ** -S# Set symble table size to accept # symbols.
- **
- ** object Name of the object file to be output. It must have a REL
- ** extension to be recognized as an output file. A drive
- ** specifier is allowed. If not specified, the object code
- ** will go into a file (on the default drive) bearing the same
- ** name as the first source file, but with a REL extension.
- ** source... Names of the source files to be assembled. The default, and
- ** only allowed, extension is MAC. A drive specifier is allowed.
- ** The named files will be assembled as one file concatenated
- ** in the order given.
- **
- ** NOTE: The module name in the REL file will be taken from
- ** the first 6 characters of the object filename.
- */
- #include <stdio.h>
- #include "notice.h"
- #include "mac.h"
- #include "rel.h"
- #include "mit.h"
- #define NOCCARGC
-
- /*
- ** symbol table
- */
- int
- stmax = STMAX, /* maximum symbols */
- stn, /* number of symbols loades */
- *stp; /* symbol table pointer array */
- char
- *st, /* symble table buffer */
- *stend, /* end of symbol tBLE */
- *stptr, /* st entry pointer */
- stsym[MAXLAB+1]; /* temporRY SYMBOL SPACE */
-
- /*
- ** macro definition table
- */
- char
- *mt, /* macro tBLE BUFFER */
- *mtprev, /* previous mt entry */
- *mtnext, /* next available mt byte */
- *mtend, /* end of macro table */
- *mtptr; /* mt entry pointer */
-
- int
- pass = 1, /* which pass? */
- badsym, /* bad symbol? */
- gotep, /* have an entry point? */
- gotxr, /* have an external reference? */
- gotlabel, /* have a label? */
- gotnam, /* have a name? */
- eom, /* end of module? */
- endv, /* END value? */
- endt, /* END type? */
- err, /* error? */
- lerr, /* line error flages */
- loc, /* location counter */
- lin, /* line counter */
- srcfd, /* source file fd */
- list, /* generate alisting? */
- lline, /* listing inene, force 1st page heading */
- part1, /* part one of listing line printed? */
- ccnt, /* count of code characters printed */
- lpage, /* listing page */
- pause, /* pause on errors? */
- looks, /* number of looks to find instruction */
- macros = YES, /* macro processing? */
- mlnext, /* next macro label to assign */
- mlnbr[10], /* macro label numbers */
- mpptr[10], /* macro parameter pointers */
- defmode, /* macro definition mode */
- expmode; /* macro expansion mode */
-
- char
- *ep, /* expression pointer */
- *lp, /* line pointer */
- line[MAXLINE], /* source line */
- *prior, /* prior ext ref in chain */
- srcfn[MAXFN+4], /* source filename */
- objfn[MAXFN+4]; /* object filename */
-
- main(argc, argv) int argc, *argv; {
- fputs("Small-Mac Assembler, ", stderr); fputs(VERSION, stderr);
- fputs(CRIGHT1, stderr);
- getsw(argc, argv); /* get command line options */
- pass1(argc, argv); /* build symbol table */
- pass2(argc, argv); /* generate object code */
- if(err) abort(7); /* sound the alarm */
- }
-
- /*
- ** pass one
- */
- pass1(argc, argv) int argc, *argv; {
- int max;
- st = calloc(STBUFSZ, 1); /* allocate zeroed symbol table */
- stp = calloc(stmax, INTSZ);
- stend = st + STBUFSZ; /* remember end of table */
- max = avail(YES); /* how much available? */
- max -= STACK + (MAXOPEN * OHDOPEN); /* calculate how much */
- mt = mtnext = calloc(max, 1); /* allocate space */
- mtend = mt + max - MAXLINE; /* note end of macro buffer */
- dopass(argc, argv); /* do pass 1 */
- }
-
- /*
- ** pass two
- */
- pass2(argc, argv) int argc, *argv; {
- int i;
- outrel = open(objfn, "w"); /* open object file */
- putname(); /* declare module name */
- putent(); /* declare entry points */
- putsz(); /* declare program size */
- pass = 2; /* signal pass 2 */
- dopass(argc, argv); /* do pass 2 */
- putexs(); /* declare ep and xr symbols */
- putend(); /* declare end of program */
- if(ferror(outrel)) err = YES;
- close(outrel); /* close object file */
- }
-
- /*
- ** process passes 1 and 2
- */
- dopass(argc, argv) int argc, *argv; {
- int mop;
- int i;
- mlnext = lpage = i = lin = loc = 0; /* reset everything */
- lline = 100; /* force page heading */
-
- while(getarg(++i, srcfn, MAXFN, argc, argv) != EOF) {
- if(srcfn[0] == '-') continue;
- if(extend(srcfn, SRCEXT, OBJEXT)) continue;
- srcfd = open(srcfn, "r"); /* open source file */
- eom = NO; /* not end of module */
- goto input;
- while(YES) {
- poll(YES);
- ++lin; lerr = 0; /* bump line counter & zero errors */
- part1 = NO; /* part 1 of line not listed */
- beglin(); /* begin a listing line */
- if(macros == NO) {
- dolabel(); /* do label and find next field */
- if(!domach()) doasm(); /* machine or assembler instr? */
- }
- else {
- lp = line;
- lp = getsym(lp, NO);
- if(!(mop = macop()) && gotnam) { /* 2nd field a token? */
- lp = skip(1, line); /* no, ttry fisrst */
- mop = macop();
- }
- if(defmode) { /* definition mode */
- if(mop == ENDM) defmode = NO;
- if(pass == 1) putmac(); /* put line in macro table */
- }
- else { /* copy or expansion mode */
- if(mop == CALL) { /* enter expansion mode */
- expmode = YES;
- putparm(); /* savew parameters */
- dolabel(); /* process label */
- }
- else if(mop == MACRO) { /* enter definition mode */
- defmode = YES;
- if(pass == 1) newmac(); /* init new macro in table */
- }
- else if(mop == ENDM) { /* leave expansion mode */
- expmode = NO;
- }
- else {
- if(expmode) replace();
- dolabel(); /* do label and find next field */
- if(!domach()) doasm(); /* machine or assembler instr? */
- }
- }
- }
- endline(); /* end a lising line */
- if(pass == 2) gripe(); /* gripe about errors */
- if(expmode) getmac(); /* fetch next macro line */
- else {
- input:
- if(eom) break;
- if(!fgets(line, MAXLINE, srcfd)) error("- Missing END");
- }
- }
- if(defmode) {err = YES; puts("- Missing ENDM");}
- close(srcfd); /* close source file */
- }
- }
-
- /*
- ** can line take more?
- */
- cantake(i, need) int i, need; {
- return (i < (MAXLINE - 3) - need);
- }
-
- /*
- ** get a line from the macro buffer
- */
- getmac() {
- char *cp; cp = line;
- while(*cp++ = *mtptr++) ;
- }
-
- /*
- ** get switches from command line
- */
- getsw(argc, argv) int argc, *argv; {
- char arg[MAXFN+4]; int i, j, len;
- i = 0;
- while(getarg(++i, arg, MAXFN, argc, argv) != EOF) {
- if(arg[0] == '-') {
- if(toupper(arg[1]) == 'L') list = YES;
- else if(toupper(arg[1]) == 'P') pause = YES;
- else if(toupper(arg[1]) == 'N' &&
- toupper(arg[2]) == 'M') macros = NO;
- else if(toupper(arg[1]) == 'S') {
- len = utoi(arg + 2, &j);
- if(len > 0 && !arg[len + 2]) stmax = j;
- else usage();
- }
- else usage();
- }
- else {
- if(extend(arg, OBJEXT, OBJEXT) || !*objfn) {
- if(arg[1] == ':') j = 2; else j = 0;
- strcpy(objfn, arg + j);
- }
- }
- }
- }
-
- /*
- ** recognize macro operation
- */
- macop() {
- if(fldcmp(lp, "ENDM" ) == 0) return (ENDM);
- if(fldcmp(lp, "MACRO") == 0) return (MACRO);
- if(!expmode && !defmode && mtfind()) return (CALL);
- return (NO);
- }
-
- /*
- ** test for macro buffer overflow
- */
- macover(ptr) char *ptr; {
- if(ptr > mtend) error("- Macro Buffer Overflow");
- }
-
- /*
- ** find stsym in macro table
- ** return true if found, else false
- ** leave mtptr pointing to body of desired macro
- */
- mtfind() {
- if(atend(*lp) == 0) {
- mtptr = mt;
- do {
- if(fldcmp(lp, mtptr + MTNAM) == 0) {
- mtptr += MTNAM;
- mtptr += strlen(mtptr) +1;
- return (YES);
- }
- mtptr = getint(mtptr);
- } while(mtptr);
- }
- return (NO);
- }
-
- /*
- ** establish new macro
- */
- newmac() {
- int i; i = 0;
- if(!gotnam || badsym) symerr();
- else {
- macover(mtnext);
- if(mtprev) putint(mtprev, mtnext);
- mtprev = mtnext;
- putint(mtnext, 0);
- mtnext += INTSZ;
- while(*mtnext++ = stsym[i++]) ;
- }
- }
-
- /*
- ** put a line in the macro buffer
- */
- putmac() {
- char *cp; cp = line;
- macover(mtnext); /* will buffer take it? */
- while(*mtnext++ = *cp++) ; /* copy everything */
- }
-
- /*
- ** save macro call parameters in macro buffer
- ** and reset labels
- */
- putparm() {
- int i, dlm; char *cp;
- i = -1; cp = mtnext;
- lp = skip(2, lp); /* skip to parameters */
- while(++i < 10) {
- mlnbr[i] = 0; /* null macro label nbr */
- while(isspace(*lp)) ++lp;
- if(atend(*lp) || *lp == ',') mpptr[i] = 0;
- else {
- macover(cp);
- mpptr[i] = cp;
- while(!atend(*lp) && *lp != ',') {
- if(*lp == '\"' || *lp == '\'') {
- dlm = *lp;
- while(!atend(*++lp)) {
- if(*lp == dlm && *++lp != dlm) break;
- *cp++ = *lp;
- }
- }
- else *cp++ = *lp++;
- }
- *cp++ = NULL;
- }
- if(*lp == ',') ++lp;
- }
- if(!atend(*lp)) parerr();
- }
-
- /*
- ** replace parameters
- */
- replace () {
- char lin[MAXLINE]; int ndx;
- char *cp, *cp2; int i;
- strcpy(lin, line); cp = lin; i = 0;
- do {
- if(*cp == '?') { /* substitution marker? */
- if(isdigit(*++cp)) { /* parameter substitution */
- ndx = *cp++ - '0' - 1; /* which one? */
- if(ndx < 0) ndx = 9; /* make 0 mean 10 */
- if(cp2 = mpptr[ndx]) { /* got parameter? */
- while(*cp2) /* yes, copy it */
- if(cantake(i, 1)) line[i++] = *cp2++;
- }
- continue;
- }
- }
- if(*cp == '@') { /* label substitution? */
- if(cantake(i, 1)) line[i++] = '@';/* insert label prefix */
- if(isdigit(*++cp)) { /* which one? */
- ndx = *cp++ - '0';
- if(!mlnbr[ndx]) mlnbr[ndx] = ++mlnext; /* need new label number? */
- if(cantake(i, 5)) {
- left(itou(mlnbr[ndx], line + i, 5)); /* insert label number */
- while(line[i]) ++i; /* bypass label number */
- }
- continue;
- }
- }
- if(cantake(i, 1)) line[i++] = *cp++;
- else {
- line[i++] = '\n';
- break;
- }
- } while(*cp);
- line[i] = NULL;
- }
-
- /*
- ** abort with message
- */
- usage() {
- error("Usage: MAC [-L] [-NM] [-P] [-S#] [object] source...");
- }
- NULL;
- }
-
- /*
- ** abort with me