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