X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=macro.c;h=5aaa842a52d78d75c4808d676b384a54d5e1d914;hp=b8097f3570fe38e3c0030ad320507c46b41adb16;hb=d0c28c349ddfb8393568037f68bddbe8979ce0df;hpb=d28f432296e812643e236d1bfc9b556a7b11c461 diff --git a/macro.c b/macro.c index b8097f3..5aaa842 100644 --- a/macro.c +++ b/macro.c @@ -1,136 +1,182 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////// +// // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System // MACRO.C - Macro Definition and Invocation // Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 -// Source Utilised with the Kind Permission of Landon Dyer +// Source utilised with the kind permission of Landon Dyer +// #include "macro.h" -#include "token.h" +#include "debug.h" +#include "direct.h" #include "error.h" #include "expr.h" #include "listing.h" -#include "symbol.h" #include "procln.h" -#include "direct.h" -#include "debug.h" +#include "symbol.h" +#include "token.h" -LONG curuniq; // Current macro's unique number -TOKEN **argp; // Free spot in argptrs[] -int macnum; // Unique number for macro definition -static LONG macuniq; // Unique-per-macro number -static SYM *curmac; // Macro currently being defined -static char **curmln; // Previous macro line (or NULL) -static VALUE argno; // Formal argument count +LONG curuniq; // Current macro's unique number +//TOKEN ** argp; // Free spot in argptrs[] +int macnum; // Unique number for macro definition +TOKEN * argPtrs[128]; // 128 arguments ought to be enough for anyone +static int argp; -static LONG *firstrpt; // First .rept line -static LONG *nextrpt; // Last .rept line -static int rptlevel; // .rept nesting level +static LONG macuniq; // Unique-per-macro number +static SYM * curmac; // Macro currently being defined +//static char ** curmln; // Previous macro line (or NULL) +static VALUE argno; // Formal argument count -// -// --- Initialize Macro Processor ------------------------------------------------------------------ -// +static LONG * firstrpt; // First .rept line +static LONG * nextrpt; // Last .rept line +static int rptlevel; // .rept nesting level -void init_macro(void) { - macuniq = 0; - macnum = 1; - argp = NULL; - ib_macro(); -} // -// ------------------------------------------------------------------------------------------------- -// Exit from a Macro; -// o pop any intervening include files and repeat blocks; -// o restore argument stack; -// o pop the macro. -// ------------------------------------------------------------------------------------------------- +// Initialize macro processor // +void InitMacro(void) +{ + macuniq = 0; + macnum = 1; +// argp = NULL; + argp = 0; +} -int exitmac(void) { - IMACRO *imacro; - TOKEN **p; - - // Pop intervening include files and .rept blocks - while(cur_inobj != NULL && cur_inobj->in_type != SRC_IMACRO) - fpop(); - - if(cur_inobj == NULL) - fatal("too many ENDMs"); - - // Restore - // o old arg context - // o old unique number - // ...and then pop the macro. - - imacro = cur_inobj->inobj.imacro; - curuniq = imacro->im_olduniq; - - p = --argp; - argp = (TOKEN **)*argp; - - fpop(); - - mjump_align = 0; - return(0); +// +// Exit from a macro; +// -- pop any intervening include files and repeat blocks; +// -- restore argument stack; +// -- pop the macro. +// +int ExitMacro(void) +{ +#warning !!! Bad macro exiting !!! +/* +This is a problem. Currently, the argument logic just keeps the current +arguments and doesn't save anything if a new macro is called in the middle +of another (nested macros). Need to fix that somehow. +*/ + // Pop intervening include files and .rept blocks + while (cur_inobj != NULL && cur_inobj->in_type != SRC_IMACRO) + fpop(); + + if (cur_inobj == NULL) + fatal("too many ENDMs"); + + // Restore + // o old arg context + // o old unique number + // ...and then pop the macro. + + IMACRO * imacro = cur_inobj->inobj.imacro; + curuniq = imacro->im_olduniq; + +// /*TOKEN ** p = */argp--; +// argp = (TOKEN **)*argp; + DEBUG printf("ExitMacro: argp: %d -> ", argp); + argp -= imacro->im_nargs; + DEBUG printf("%d (nargs = %d)\n", argp, imacro->im_nargs); + + fpop(); + return 0; } + // -// --- Add a Formal Argument to a Macro Definition ------------------------------------------------- +// Add a formal argument to a macro definition // +int defmac2(char * argname) +{ + SYM * arg; -int defmac2(char *argname) { - SYM *arg; + if (lookup(argname, MACARG, (int)curmac->sattr) != NULL) + return error("multiple formal argument definition"); - if(lookup(argname, MACARG, (int)curmac->sattr) != NULL) - return(error("multiple formal argument definition")); - arg = newsym(argname, MACARG, (int)curmac->sattr); - arg->svalue = argno++; + arg = NewSymbol(argname, MACARG, (int)curmac->sattr); + arg->svalue = argno++; - return(OK); + return OK; } // -// ------------------------------------------------------------------------------------------------- -// Add a line to a macro definition; also print lines to listing file (if enabled). -// The last line of the macro (containing .endm) is not included in the macro. A label on that line -// will be lost. `endflg' is misleading here. It is -1 for all lines but the last one (.endm), -// when it is 0. -// ------------------------------------------------------------------------------------------------- +// Add a line to a macro definition; also print lines to listing file (if +// enabled). The last line of the macro (containing .endm) is not included in +// the macro. A label on that line will be lost. +// notEndFlag is -1 for all lines but the last one (.endm), when it is 0. // - -int defmac1(char *ln, int endflg) { - PTR p; - LONG len; - - if(list_flag) { - listeol(); // Flush previous source line - lstout('.'); // Mark macro definition with period - } - - if(endflg) { - len = strlen(ln) + 1 + sizeof(LONG); - p.cp = amem(len); - *p.lp = 0; - strcpy(p.cp + sizeof(LONG), ln); - - // Link line of text onto end of list - if(curmln == NULL) - curmac->svalue = (VALUE)p.cp; - else - *curmln = p.cp; - curmln = (char **)p.cp; - return(1); // Keep looking - } - else - return(0); // Stop looking at the end +int defmac1(char * ln, int notEndFlag) +{ + PTR p; + LONG len; + + if (list_flag) + { + listeol(); // Flush previous source line + lstout('.'); // Mark macro definition with period + } + + // This is just wrong, wrong, wrong. It makes up a weird kind of string with + // a pointer on front, and then uses a ** to manage them: This is a recipe + // for disaster. + // How to manage it then? + // Could use a linked list, like Landon uses everywhere else. +/* +How it works: +Allocate a space big enough for the string + NULL + pointer. +Set the pointer to NULL. +Copy the string to the space after the pointer. +If this is the 1st time through, set the SYM * "svalue" to the pointer. +If this is the 2nd time through, derefence the ** to point to the memory you just allocated. +Then, set the ** to the location of the memory you allocated for the next pass through. + +This is a really low level way to do a linked list, and by bypassing all the safety +features of the language. Seems like we can do better here. +*/ + if (notEndFlag) + { +#if 0 + len = strlen(ln) + 1 + sizeof(LONG); + p.cp = malloc(len); + *p.lp = 0; + strcpy(p.cp + sizeof(LONG), ln); + + // Link line of text onto end of list + if (curmln == NULL) + curmac->svalue = p.cp; + else + *curmln = p.cp; + + curmln = (char **)p.cp; + return 1; // Keep looking +#else + if (curmac->lineList == NULL) + { + curmac->lineList = malloc(sizeof(struct LineList)); + curmac->lineList->next = NULL; + curmac->lineList->line = strdup(ln); + curmac->last = curmac->lineList; + } + else + { + curmac->last->next = malloc(sizeof(struct LineList)); + curmac->last->next->next = NULL; + curmac->last->next->line = strdup(ln); + curmac->last = curmac->last->next; + } + + return 1; // Keep looking +#endif + } + + return 0; // Stop looking at the end } + // -// ------------------------------------------------------------------------------------------------- // Define macro // // macro foo arg1,arg2,... @@ -142,348 +188,421 @@ int defmac1(char *ln, int endflg) { // ----------------- // `defmac1' adds lines of text to the macro definition // `defmac2' processes the formal arguments (and sticks them into the symbol table) -// ------------------------------------------------------------------------------------------------- // - -int defmac(void) { - char *p; - SYM *mac; - - // Setup entry in symbol table, make sure the macro isn't a duplicate entry, and that - // it doesn't override any processor mnemonic or assembler directive. - if(*tok++ != SYMBOL) return(error("missing symbol")); - p = (char *)*tok++; - if(lookup(p, MACRO, 0) != NULL) - return(error("multiple macro definition")); - - curmac = mac = newsym(p, MACRO, 0); - mac->svalue = 0; - mac->sattr = (WORD)(macnum++); - - // Parse and define formal arguments in symbol table - if(*tok != EOL) { - argno = 0; - symlist(defmac2); - at_eol(); - } - - // Suck in the macro definition; we're looking for an ENDM symbol on a line - // by itself to terminate the definition. - curmln = NULL; - lncatch(defmac1, "endm "); - - return(0); +int DefineMacro(void) +{ + // Setup entry in symbol table, make sure the macro isn't a duplicate + // entry, and that it doesn't override any processor mnemonic or assembler + // directive. + if (*tok++ != SYMBOL) + return error("missing symbol"); + + char * name = string[*tok++]; + + if (lookup(name, MACRO, 0) != NULL) + return error("duplicate macro definition"); + + curmac = NewSymbol(name, MACRO, 0); + curmac->svalue = 0; + curmac->sattr = (WORD)(macnum++); + + // Parse and define formal arguments in symbol table + if (*tok != EOL) + { + argno = 0; + symlist(defmac2); + at_eol(); + } + + // Suck in the macro definition; we're looking for an ENDM symbol on a line + // by itself to terminate the definition. +// curmln = NULL; + curmac->lineList = NULL; + lncatch(defmac1, "endm "); + + return 0; } + // -// --- Add lines to a .rept definition ------------------------------------------------------------- +// Add lines to a .rept definition // - -int defr1(char *ln, int kwno) { - LONG len; - LONG *p; - - if(list_flag) { - listeol(); // Flush previous source line - lstout('#'); // Mark this a 'rept' block - } - - switch(kwno) { - case 0: // .endr - if(--rptlevel == 0) - return(0); - goto addln; - case 1: // .rept - ++rptlevel; - default: - - addln: - - // Allocate length of line + 1('\0') + LONG - len = strlen(ln) + 1 + sizeof(LONG); - p = (LONG *)amem(len); - *p = 0; - - strcpy((char*)(p + 1), ln); - - if(nextrpt == NULL) { - firstrpt = p; // First line of rept statement - } else { - *nextrpt = (LONG)p; - } - nextrpt = p; - - return(rptlevel); - } +int defr1(char * ln, int kwno) +{ + LONG len; + LONG * p; + + if (list_flag) + { + listeol(); // Flush previous source line + lstout('#'); // Mark this a 'rept' block + } + + switch (kwno) + { + case 0: // .endr + if (--rptlevel == 0) + return(0); + goto addln; + case 1: // .rept + rptlevel++; + default: +//MORE stupidity here... +#warning "!!! Casting (char *) as LONG !!!" + addln: + // Allocate length of line + 1('\0') + LONG + len = strlen(ln) + 1 + sizeof(LONG); +// p = (LONG *)amem(len); + p = (LONG *)malloc(len); + *p = 0; + + strcpy((char *)(p + 1), ln); + + if (nextrpt == NULL) + { + firstrpt = p; // First line of rept statement + } + else + { + *nextrpt = (LONG)p; + } + + nextrpt = p; + + return rptlevel; + } } + // -// --- Define a .rept block, this gets hairy because they can be nested ---------------------------- +// Define a .rept block, this gets hairy because they can be nested // - -int defrept(void) { - INOBJ *inobj; - IREPT *irept; - VALUE eval; - - // Evaluate repeat expression - if(abs_expr(&eval) != OK) - return(ERROR); - - // Suck in lines for .rept block - firstrpt = NULL; - nextrpt = NULL; - rptlevel = 1; - lncatch(defr1, "endr rept "); - - // Alloc and init input object - if(firstrpt) { - inobj = a_inobj(SRC_IREPT); // Create a new REPT input object - irept = inobj->inobj.irept; - irept->ir_firstln = firstrpt; - irept->ir_nextln = NULL; - irept->ir_count = eval; - } - - return(0); +int defrept(void) +{ + INOBJ * inobj; + IREPT * irept; + VALUE eval; + + // Evaluate repeat expression + if (abs_expr(&eval) != OK) + return ERROR; + + // Suck in lines for .rept block + firstrpt = NULL; + nextrpt = NULL; + rptlevel = 1; + lncatch(defr1, "endr rept "); + + // Alloc and init input object + if (firstrpt) + { + inobj = a_inobj(SRC_IREPT); // Create a new REPT input object + irept = inobj->inobj.irept; + irept->ir_firstln = firstrpt; + irept->ir_nextln = NULL; + irept->ir_count = eval; + } + + return 0; } + // -// ------------------------------------------------------------------------------------------------- -// Hand off lines of text to the function `lnfunc' until a line containing one of the directives in -// `dirlist' is encountered. Return the number of the keyword encountered (0..n) +// Hand off lines of text to the function `lnfunc' until a line containing one +// of the directives in `dirlist' is encountered. Return the number of the +// keyword encountered (0..n) // -// `dirlist' contains null-seperated terminated keywords. A final null terminates the list. -// Directives are compared to the keywords without regard to case. +// `dirlist' contains null-seperated terminated keywords. A final null +// terminates the list. Directives are compared to the keywords without regard +// to case. // // If `lnfunc' is NULL, then lines are simply skipped. // If `lnfunc' returns an error, processing is stopped. // -// `lnfunc' is called with an argument of -1 for every line but the last one, when it is called -// with an argument of the keyword number that caused the match. -// ------------------------------------------------------------------------------------------------- +// `lnfunc' is called with an argument of -1 for every line but the last one, +// when it is called with an argument of the keyword number that caused the +// match. // - -int lncatch(int (*lnfunc)(), char *dirlist) { - char *p; - int k; - - if(lnfunc != NULL) - ++lnsave; // Tell tokenizer to keep lines - - for(;;) { - if(tokln() == TKEOF) { - errors("encountered end-of-file looking for '%s'", dirlist); - fatal("cannot continue"); - } - - // Test for end condition. Two cases to handle: - // - // symbol: - p = NULL; - k = -1; - - if(*tok == SYMBOL) { - if((tok[2] == ':' || tok[2] == DCOLON)) { - if(tok[3] == SYMBOL) // label: symbol - p = (char *)tok[4]; - } else { - p = (char *)tok[1]; // symbol - } - } - - if(p != NULL) { - if(*p == '.') // ignore leading '.'s - ++p; - k = kwmatch(p, dirlist); - } - - // Hand-off line to function - // if it returns 0, and we found a keyword, stop looking. - // if it returns 1, hand off the line and keep looking. - if(lnfunc != NULL) - k = (*lnfunc)(lnbuf, k); - - if(!k) - break; - } - - if(lnfunc != NULL) - --lnsave; // Tell tokenizer to stop keeping lines - - return(0); +int lncatch(int (* lnfunc)(), char * dirlist) +{ + char * p; + int k; + + if (lnfunc != NULL) + lnsave++; // Tell tokenizer to keep lines + + for(;;) + { + if (TokenizeLine() == TKEOF) + { + errors("encountered end-of-file looking for '%s'", dirlist); + fatal("cannot continue"); + } + + // Test for end condition. Two cases to handle: + // + // symbol: + p = NULL; + k = -1; + + if (*tok == SYMBOL) + { + if ((tok[2] == ':' || tok[2] == DCOLON)) + { + if (tok[3] == SYMBOL) // label: symbol + p = string[tok[4]]; + } + else + { + p = string[tok[1]]; // Symbol + } + } + + if (p != NULL) + { + if (*p == '.') // ignore leading '.'s + p++; + + k = kwmatch(p, dirlist); + } + + // Hand-off line to function + // if it returns 0, and we found a keyword, stop looking. + // if it returns 1, hand off the line and keep looking. + if (lnfunc != NULL) + k = (*lnfunc)(lnbuf, k); + + if (!k) + break; + } + + if (lnfunc != NULL) + lnsave--; // Tell tokenizer to stop keeping lines + + return 0; } + // -// ------------------------------------------------------------------------------------------------- -// See if the string `kw' matches one of the keywords in `kwlist'. If so, return the number of -// the keyword matched. Return -1 if there was no match. +// See if the string `kw' matches one of the keywords in `kwlist'. If so, +// return the number of the keyword matched. Return -1 if there was no match. // Strings are compared without regard for case. -// ------------------------------------------------------------------------------------------------- // - -int kwmatch(char *kw, char *kwlist) { - char *p; - char c1; - char c2; - int k; - - for(k = 0; *kwlist; ++k) { - for(p = kw;;) { - c1 = *kwlist++; - c2 = *p++; - - if(c2 >= 'A' && c2 <= 'Z') - c2 += 32; - - if(c1 == ' ' && c2 == EOS) - return(k); - - if(c1 != c2) - break; - } - - // Skip to beginning of next keyword in `kwlist' - while(*kwlist && *kwlist != ' ') - ++kwlist; - if(*kwlist== ' ') - ++kwlist; - } - - return(-1); +int kwmatch(char * kw, char * kwlist) +{ + char * p; + char c1; + char c2; + int k; + + for(k=0; *kwlist; ++k) + { + for(p=kw;;) + { + c1 = *kwlist++; + c2 = *p++; + + if (c2 >= 'A' && c2 <= 'Z') + c2 += 32; + + if (c1 == ' ' && c2 == EOS) + return k; + + if (c1 != c2) + break; + } + + // Skip to beginning of next keyword in `kwlist' + while (*kwlist && *kwlist != ' ') + ++kwlist; + + if (*kwlist== ' ') + kwlist++; + } + + return -1; } + // -// ------------------------------------------------------------------------------------------------- // Invoke a macro // o parse, count and copy arguments // o push macro's string-stream -// ------------------------------------------------------------------------------------------------- // - -int invokemac(SYM *mac, WORD siz) { - TOKEN *p = NULL; - IMACRO *imacro; - INOBJ *inobj; - int dry_run; - WORD nargs; - WORD arg_siz = 0; - TOKEN **argptr = NULL; - TOKEN *beg_tok; - - if((!strcmp(mac->sname, "mjump") || !strcmp(mac->sname, "mpad")) && !in_main) { - error("macro cannot be used outside of .gpumain"); - return(ERROR); - } - - inobj = a_inobj(SRC_IMACRO); // Alloc and init IMACRO - imacro = inobj->inobj.imacro; - imacro->im_siz = siz; - nargs = 0; - beg_tok = tok; - - for(dry_run = 1;; --dry_run) { - for(tok = beg_tok; *tok != EOL;) { - if(dry_run) ++nargs; - else *argptr++ = p; - - while(*tok != ',' && *tok != EOL) { - if(*tok == '\\' && tok[1] != EOL) ++tok; - switch((int)*tok) { - case CONST: - case SYMBOL: - case ACONST: - if(dry_run) arg_siz += sizeof(TOKEN), ++tok; - else *p++ = *tok++; - // FALLTHROUGH - default: - if(dry_run) arg_siz += sizeof(TOKEN), ++tok; - else *p++ = *tok++; - break; - } - } - - if(dry_run) arg_siz += sizeof(TOKEN); - else *p++ = EOL; - - if(*tok == ',') ++tok; - } - - // Allocate space for argument ptrs and so on and then go back and construct the arg frame - if(dry_run) { - if(nargs != 0) p = (TOKEN *)malloc((LONG)(arg_siz + 1)); - argptr = (TOKEN **)malloc((LONG)((nargs + 1) * sizeof(LONG))); - *argptr++ = (TOKEN *)argp; - argp = argptr; - } else - break; - } - - - // Setup imacro: - // o #arguments; - // o -> macro symbol; - // o -> macro definition string list; - // o save 'curuniq', to be restored when the macro pops; - // o bump `macuniq' counter and set 'curuniq' to it; - imacro->im_nargs = nargs; - imacro->im_macro = mac; - imacro->im_nextln = (LONG *)mac->svalue; - imacro->im_olduniq = curuniq; - curuniq = ++macuniq; - - DEBUG { - printf("nargs=%d\n", nargs); - for(nargs = 0; nargs < imacro->im_nargs; ++nargs) { - printf("arg%d=", nargs); - dumptok(argp[imacro->im_nargs - nargs - 1]); - } - } - - return(OK); +int InvokeMacro(SYM * mac, WORD siz) +{ + TOKEN * p = NULL; + int dry_run; + WORD arg_siz = 0; +// TOKEN ** argptr = NULL; +//Doesn't need to be global! (or does it???--it does) +// argp = 0; + DEBUG printf("InvokeMacro: argp: %d -> ", argp); + + INOBJ * inobj = a_inobj(SRC_IMACRO); // Alloc and init IMACRO + IMACRO * imacro = inobj->inobj.imacro; + imacro->im_siz = siz; + WORD nargs = 0; + TOKEN * beg_tok = tok; // 'tok' comes from token.c + TOKEN * startOfArg; + TOKEN * dest; + int stringNum = 0; + int argumentNum = 0; + int i; + + for(dry_run=1; ; dry_run--) + { + for(tok=beg_tok; *tok!=EOL;) + { + if (dry_run) + nargs++; + else + { +#if 0 + *argptr++ = p; +#else + argPtrs[argp++] = p; + startOfArg = p; +#endif + } + + // Keep going while tok isn't pointing at a comma or EOL + while (*tok != ',' && *tok != EOL) + { + // Skip over backslash character, unless it's followed by an EOL + if (*tok == '\\' && tok[1] != EOL) + tok++; + + switch (*tok) + { + case CONST: + case SYMBOL: +//Shamus: Possible bug. ACONST has 2 tokens after it, not just 1 + case ACONST: + if (dry_run) + { + arg_siz += sizeof(TOKEN); + tok++; + } + else + { + *p++ = *tok++; + } + // FALLTHROUGH (picks up the arg after a CONST, SYMBOL or ACONST) + default: + if (dry_run) + { + arg_siz += sizeof(TOKEN); + tok++; + } + else + { + *p++ = *tok++; + } + + break; + } + } + + // We hit the comma or EOL, so count/stuff it + if (dry_run) + arg_siz += sizeof(TOKEN); + else + *p++ = EOL; + + // If we hit the comma instead of an EOL, skip over it + if (*tok == ',') + tok++; + + // Do our QnD token grabbing (this will be redone once we get all + // the data structures fixed as this is a really dirty hack) + if (!dry_run) + { + dest = imacro->argument[argumentNum].token; + stringNum = 0; + + do + { + // Remap strings to point the IMACRO internal token storage + if (*startOfArg == SYMBOL || *startOfArg == STRING) + { + *dest++ = *startOfArg++; + imacro->argument[argumentNum].string[stringNum] = strdup(string[*startOfArg++]); + *dest++ = stringNum++; + } + else + *dest++ = *startOfArg++; + } + while (*startOfArg != EOL); + + *dest = *startOfArg; // Copy EOL... + argumentNum++; + } + } + + // Allocate space for argument ptrs and so on and then go back and + // construct the arg frame + if (dry_run) + { + if (nargs != 0) + p = (TOKEN *)malloc(arg_siz); +// p = (TOKEN *)malloc(arg_siz + sizeof(TOKEN)); + +/* +Shamus: +This construct is meant to deal with nested macros, so the simple minded way +we deal with them now won't work. :-/ Have to think about how to fix. +What we could do is simply move the argp with each call, and move it back by +the number of arguments in the macro that's ending. That would solve the +problem nicely. +[Which we do now. But that uncovered another problem: the token strings are all +stale by the time a nested macro gets to the end. But they're supposed to be +symbols, which means if we put symbol references into the argument token +streams, we can alleviate this problem.] +*/ +#if 0 + argptr = (TOKEN **)malloc((nargs + 1) * sizeof(LONG)); + *argptr++ = (TOKEN *)argp; + argp = argptr; +#else + // We don't need to do anything here since we already advance argp + // when parsing the arguments. +// argp += nargs; +#endif + } + else + break; + } + + DEBUG printf("%d\n", argp); + + // Setup imacro: + // o # arguments; + // o -> macro symbol; + // o -> macro definition string list; + // o save 'curuniq', to be restored when the macro pops; + // o bump `macuniq' counter and set 'curuniq' to it; + imacro->im_nargs = nargs; + imacro->im_macro = mac; +// imacro->im_nextln = (TOKEN *)mac->svalue; + imacro->im_nextln = mac->lineList; + imacro->im_olduniq = curuniq; + curuniq = macuniq++; + imacro->argBase = argp - nargs; // Shamus: keep track of argument base + + DEBUG + { + printf("nargs=%d\n", nargs); + + for(nargs=0; nargsim_nargs; nargs++) + { + printf("arg%d=", nargs); +// dumptok(argp[imacro->im_nargs - nargs - 1]); +// dumptok(argPtrs[imacro->im_nargs - nargs - 1]); + dumptok(argPtrs[(argp - imacro->im_nargs) + nargs]); + } + } + + return OK; } -// -// ------------------------------------------------------------------------------------------------- -// Setup inbuilt macros -// ------------------------------------------------------------------------------------------------- -// - -void ib_macro(void) { - SYM *mac; - - curmac = mac = newsym("mjump", MACRO, 0); - mac->svalue = 0; - mac->sattr = (WORD)(macnum++); - argno = 0; - defmac2("cc"); - defmac2("addr"); - defmac2("jreg"); - curmln = NULL; - defmac1(" nop", -1); - defmac1(" movei #\\addr,\\jreg", -1); - defmac1(" jump \\cc,(\\jreg)", -1); - defmac1(" nop", -1); - defmac1(" nop", -1); - - curmac = mac = newsym("mjr", MACRO, 0); - mac->svalue = 0; - mac->sattr = (WORD)(macnum++); - argno = 0; - defmac2("cc"); - defmac2("addr"); - curmln = NULL; - defmac1(" jr \\cc,\\addr", -1); - defmac1(" nop", -1); - defmac1(" nop", -1); - - curmac = mac = newsym("mpad", MACRO, 0); - mac->svalue = 0; - mac->sattr = (WORD)(macnum++); - argno = 0; - defmac2("size"); - curmln = NULL; - defmac1(" .rept (\\size/2)", -1); - defmac1(" nop", -1); - defmac1(" .endr", -1); -} \ No newline at end of file