]> Shamusworld >> Repos - rmac/blobdiff - macro.c
Actually implement ^^FILESIZE this time :)
[rmac] / macro.c
diff --git a/macro.c b/macro.c
index 8731fb87e43ad13b21109e440884ddf8dec6812c..22bd0d9f7c444d4824228cab8307e82c648c9f85 100644 (file)
--- a/macro.c
+++ b/macro.c
@@ -1,58 +1,65 @@
 //
-// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
+// RMAC - Reboot's Macro Assembler for all Atari computers
 // MACRO.C - Macro Definition and Invocation
-// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2011-2020 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
+int macnum;                                    // Unique number for macro definition
 
-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 uint32_t argno;                 // Formal argument count
 
-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 
+static LLIST * firstrpt;       // First .rept line
+static LLIST * nextrpt;                // Last .rept line
+static int rptlevel;           // .rept nesting level
 
-static LONG * firstrpt;                                                // First .rept line 
-static LONG * nextrpt;                                         // Last .rept line 
-static int rptlevel;                                           // .rept nesting level 
+// Function prototypes
+static int KWMatch(char *, char *);
+static int LNCatch(int (*)(), char *);
 
 
 //
-// Initialize Macro Processor
+// Initialize macro processor
 //
-void init_macro(void)
+void InitMacro(void)
 {
        macuniq = 0;
        macnum = 1;
-       argp = NULL;
-       ib_macro();
 }
 
 
 //
-// Exit from a Macro;
-//  pop any intervening include files and repeat blocks;
-//  restore argument stack;
-//  pop the macro.
+// Exit from a macro;
+// -- pop any intervening include files and repeat blocks;
+// -- restore argument stack;
+// -- pop the macro.
 //
-int exitmac(void)
+int ExitMacro(void)
 {
-       IMACRO * imacro;
-       TOKEN ** p;
-
+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.
+
+Is this still true, now that we have IMACROs with TOKENSTREAMs in them? Need to
+check it out for sure...!
+*/
        // Pop intervening include files and .rept blocks
        while (cur_inobj != NULL && cur_inobj->in_type != SRC_IMACRO)
                fpop();
@@ -65,30 +72,24 @@ int exitmac(void)
        // o  old unique number
        // ...and then pop the macro.
 
-       imacro = cur_inobj->inobj.imacro;
+       IMACRO * imacro = cur_inobj->inobj.imacro;
        curuniq = imacro->im_olduniq;
 
-       p = --argp;
-       argp = (TOKEN **)*argp;
-
-       fpop();
-
-       mjump_align = 0;
+       DEBUG { printf("ExitMacro: nargs = %d\n", imacro->im_nargs); }
 
-       return 0;
+       return fpop();
 }
 
 
 //
-// Add a Formal Argument to a Macro Definition
+// Add a formal argument to a macro definition
 //
 int defmac2(char * argname)
 {
-       SYM * arg;
-
        if (lookup(argname, MACARG, (int)curmac->sattr) != NULL)
-               return(error("multiple formal argument definition"));
-       arg = newsym(argname, MACARG, (int)curmac->sattr);
+               return error("multiple formal argument definition");
+
+       SYM * arg = NewSymbol(argname, MACARG, (int)curmac->sattr);
        arg->svalue = argno++;
 
        return OK;
@@ -98,39 +99,40 @@ int defmac2(char * argname)
 //
 // 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.
+// 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)
+int defmac1(char * ln, int notEndFlag)
 {
-       PTR p;
-       LONG len;
-
        if (list_flag)
        {
-               listeol();                                                              // Flush previous source line
-               lstout('.');                                                    // Mark macro definition with period
+               listeol();              // Flush previous source line
+               lstout('.');    // Mark macro definition with period
        }
 
-       if (endflg)
+       if (notEndFlag)
        {
-               len = strlen(ln) + 1 + sizeof(LONG);
-//             p.cp = amem(len);
-               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 = (VALUE)p.cp;
+               if (curmac->lineList == NULL)
+               {
+                       curmac->lineList = malloc(sizeof(LLIST));
+                       curmac->lineList->next = NULL;
+                       curmac->lineList->line = strdup(ln);
+                       curmac->lineList->lineno = curlineno;
+                       curmac->last = curmac->lineList;
+               }
                else
-                       *curmln = p.cp;
+               {
+                       curmac->last->next = malloc(sizeof(LLIST));
+                       curmac->last->next->next = NULL;
+                       curmac->last->next->line = strdup(ln);
+                       curmac->lineList->lineno = curlineno;
+                       curmac->last = curmac->last->next;
+               }
 
-               curmln = (char **)p.cp;
-               return 1;                                                               // Keep looking 
+               return 1;               // Keep looking
        }
-       else 
-               return 0;                                                               // Stop looking at the end
+
+       return 0;                       // Stop looking; at the end
 }
 
 
@@ -145,39 +147,39 @@ int defmac1(char * ln, int endflg)
 //  Helper functions:
 //  -----------------
 //  `defmac1' adds lines of text to the macro definition
-//  `defmac2' processes the formal arguments (and sticks them into the symbol table)
+//  `defmac2' processes the formal arguments (and sticks them into the symbol
+//   table)
 //
-int defmac(void)
+int DefineMacro(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.
+       // 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++;
+       char * name = string[*tok++];
 
-       if (lookup(p, MACRO, 0) != NULL)
-               return error("multiple macro definition");
+       if (lookup(name, MACRO, 0) != NULL)
+               return error("duplicate macro definition");
 
-       curmac = mac = newsym(p, MACRO, 0);
-       mac->svalue = 0;
-       mac->sattr = (WORD)(macnum++);
+       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();
+               ErrorIfNotAtEOL();
        }
 
        // 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 ");
+//     curmln = NULL;
+       curmac->lineList = NULL;
+       LNCatch(defmac1, "endm ");
 
        return 0;
 }
@@ -186,59 +188,67 @@ int defmac(void)
 //
 // Add lines to a .rept definition
 //
-int defr1(char * ln, int kwno)
+int defr1(char * line, int kwno)
 {
-       LONG len;
-       LONG * p;
-
        if (list_flag)
        {
-               listeol();                                                              // Flush previous source line
-               lstout('#');                                                    // Mark this a 'rept' block
+               listeol();                      // Flush previous source line
+               lstout('#');            // Mark this a 'rept' block
        }
 
-       switch (kwno)
+       if (kwno == 0)                  // .endr
        {
-       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 = (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;
+                       return 0;
+       }
+       else if (kwno == 1)             // .rept
+               rptlevel++;
+
+//DEBUG { printf("  defr1: line=\"%s\", kwno=%d, rptlevel=%d\n", line, kwno, rptlevel); }
+
+#if 0
+//MORE stupidity here...
+WARNING("!!! Casting (char *) as LONG !!!")
+       // Allocate length of line + 1('\0') + LONG
+       LONG * p = (LONG *)malloc(strlen(line) + 1 + sizeof(LONG));
+       *p = 0;
+       strcpy((char *)(p + 1), line);
+
+       if (nextrpt == NULL)
+               firstrpt = p;           // First line of rept statement
+       else
+               *nextrpt = (LONG)p;
+
+       nextrpt = p;
+#else
+       if (firstrpt == NULL)
+       {
+               firstrpt = malloc(sizeof(LLIST));
+               firstrpt->next = NULL;
+               firstrpt->line = strdup(line);
+               firstrpt->lineno = curlineno;
+               nextrpt = firstrpt;
        }
+       else
+       {
+               nextrpt->next = malloc(sizeof(LLIST));
+               nextrpt->next->next = NULL;
+               nextrpt->next->line = strdup(line);
+               nextrpt->next->lineno = curlineno;
+               nextrpt = nextrpt->next;
+       }
+#endif
+
+       return rptlevel;
 }
 
 
 //
-// Define a .rept block, this gets hairy because they can be nested
+// Handle a .rept block; this gets hairy because they can be nested
 //
-int defrept(void)
+int HandleRept(void)
 {
-       INOBJ * inobj;
-       IREPT * irept;
-       VALUE eval;
+       uint64_t eval;
 
        // Evaluate repeat expression
        if (abs_expr(&eval) != OK)
@@ -248,16 +258,17 @@ int defrept(void)
        firstrpt = NULL;
        nextrpt = NULL;
        rptlevel = 1;
-       lncatch(defr1, "endr rept ");
+       LNCatch(defr1, "endr rept ");
 
+//DEBUG { printf("HandleRept: firstrpt=$%X\n", firstrpt); }
        // Alloc and init input object
        if (firstrpt)
        {
-               inobj = a_inobj(SRC_IREPT);                             // Create a new REPT input object
-               irept = inobj->inobj.irept;
+               INOBJ * inobj = a_inobj(SRC_IREPT);     // Create a new REPT input object
+               IREPT * irept = inobj->inobj.irept;
                irept->ir_firstln = firstrpt;
                irept->ir_nextln = NULL;
-               irept->ir_count = eval;
+               irept->ir_count = (uint32_t)eval;
        }
 
        return 0;
@@ -265,62 +276,63 @@ int defrept(void)
 
 
 //
-// 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.
-// 
-// 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,
+// Hand off lines of text to the function 'lnfunc' until a line containing one
+// of the directives in 'dirlist' is encountered.
+//
+// 'dirlist' contains space-separated terminated keywords. A final space
+// terminates the list. Directives are case-insensitively compared to the
+// keywords.
+//
+// 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.
 //
-int lncatch(int (* lnfunc)(), char * dirlist)
+static int LNCatch(int (* lnfunc)(), char * dirlist)
 {
-       char * p;
-       int k;
-
        if (lnfunc != NULL)
-               ++lnsave;                                                               // Tell tokenizer to keep lines 
+               lnsave++;                       // Tell tokenizer to keep lines
 
-       for(;;)
+       while (1)
        {
-               if (tokln() == TKEOF)
+               if (TokenizeLine() == TKEOF)
                {
-                       errors("encountered end-of-file looking for '%s'", dirlist);
+                       error("encountered end-of-file looking for '%s'", dirlist);
                        fatal("cannot continue");
                }
 
+               DEBUG { DumpTokenBuffer(); }
+
                // Test for end condition.  Two cases to handle:
                //            <directive>
                //    symbol: <directive>
-               p = NULL;
-               k = -1;
+               char * p = NULL;
+               int k = -1;
 
                if (*tok == SYMBOL)
                {
+                       // A string followed by a colon or double colon is a symbol and
+                       // *not* a directive, see if we can find the directive after it
                        if ((tok[2] == ':' || tok[2] == DCOLON))
                        {
-                               if (tok[3] == SYMBOL)                   // label: symbol
-                                       p = (char *)tok[4];
+                               if (tok[3] == SYMBOL)
+                                       p = string[tok[4]];
                        }
                        else
                        {
-                               p = (char *)tok[1];                             // symbol 
+                               // Otherwise, just grab the directive
+                               p = string[tok[1]];
                        }
                }
 
                if (p != NULL)
                {
-                       if (*p == '.')                                          // ignore leading '.'s 
-                               ++p;
+                       if (*p == '.')          // Ignore leading periods
+                               p++;
 
-                       k = kwmatch(p, dirlist);
+                       k = KWMatch(p, dirlist);
                }
 
                // Hand-off line to function
@@ -329,35 +341,30 @@ int lncatch(int (* lnfunc)(), char * dirlist)
                if (lnfunc != NULL)
                        k = (*lnfunc)(lnbuf, k);
 
-               if (!k)
+               if (k == 0)
                        break;
        }
 
        if (lnfunc != NULL)
-               --lnsave;                                                               // Tell tokenizer to stop keeping lines
+               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)
+static int KWMatch(char * kw, char * kwlist)
 {
-       char * p;
-       char c1;
-       char c2;
-       int k;
-
-       for(k=0; *kwlist; ++k)
+       for(int k=0; *kwlist; k++)
        {
-               for(p=kw;;)
+               for(char * p=kw;;)
                {
-                       c1 = *kwlist++;
-                       c2 = *p++;
+                       char c1 = *kwlist++;
+                       char c2 = *p++;
 
                        if (c2 >= 'A' && c2 <= 'Z')
                                c2 += 32;
@@ -370,11 +377,11 @@ int kwmatch(char * kw, char * kwlist)
                }
 
                // Skip to beginning of next keyword in `kwlist'
-               while (*kwlist && *kwlist != ' ')
+               while (*kwlist && (*kwlist != ' '))
                        ++kwlist;
 
                if (*kwlist== ' ')
-                       ++kwlist;
+                       kwlist++;
        }
 
        return -1;
@@ -382,178 +389,90 @@ int kwmatch(char * kw, char * kwlist)
 
 
 //
-// Invoke a macro
-// o  parse, count and copy arguments
-// o  push macro's string-stream
+// Invoke a macro by creating a new IMACRO object & chopping up the arguments
 //
-int invokemac(SYM * mac, WORD siz)
+int InvokeMacro(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;
-       }
+       DEBUG { printf("InvokeMacro: arguments="); DumpTokens(tok); }
 
-       inobj = a_inobj(SRC_IMACRO);                            // Alloc and init IMACRO 
-       imacro = inobj->inobj.imacro;
-       imacro->im_siz = siz;
-       nargs = 0;
-       beg_tok = tok;                                                          // 'tok' comes from token.c
+       INOBJ * inobj = a_inobj(SRC_IMACRO);    // Alloc and init IMACRO
+       IMACRO * imacro = inobj->inobj.imacro;
+       uint16_t nargs = 0;
 
-       for(dry_run=1;; --dry_run)
+       // Chop up the arguments, if any (tok comes from token.c, which at this
+       // point points at the macro argument token stream)
+       if (*tok != EOL)
        {
-               for(tok=beg_tok; *tok!=EOL;)
-               {
-                       if (dry_run)
-                               nargs++;
-                       else
-                               *argptr++ = p;
+               // Parse out the arguments and set them up correctly
+               TOKEN * p = imacro->argument[nargs].token;
+               int stringNum = 0;
 
-                       // Keep going while tok isn't pointing at a comma or EOL
-                       while (*tok != ',' && *tok != EOL)
+               while (*tok != EOL)
+               {
+                       if (*tok == ACONST)
                        {
-                               // Skip over backslash character, unless it's followed by an EOL
-                               if (*tok == '\\' && tok[1] != EOL)
-                                       tok++;
-
-                               switch (*tok)
-                               {
-                               case CONST:
-                               case SYMBOL:
-                               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;
-                               }
+                               for(int i=0; i<3; i++)
+                                       *p++ = *tok++;
                        }
-
-                       // We hit the comma or EOL, so count/stuff it
-                       if (dry_run)
-                               arg_siz += sizeof(TOKEN);
-                       else
+                       else if (*tok == CONST)         // Constants are 64-bits
+                       {
+                               *p++ = *tok++;                  // Token
+                               uint64_t *p64 = (uint64_t *)p;
+                               uint64_t *tok64 = (uint64_t *)tok;
+                               *p64++ = *tok64++;
+                               tok = (TOKEN *)tok64;
+                               p = (uint32_t *)p64;
+                       }
+                       else if ((*tok == STRING) || (*tok == SYMBOL))
+                       {
+                               *p++ = *tok++;
+                               imacro->argument[nargs].string[stringNum] = strdup(string[*tok++]);
+                               *p++ = stringNum++;
+                       }
+                       else if (*tok == ',')
+                       {
+                               // Comma delimiter was found, so set up for next argument
                                *p++ = EOL;
-
-                       // If we hit the comma instead of an EOL, skip over it
-                       if (*tok == ',')
                                tok++;
+                               stringNum = 0;
+                               nargs++;
+                               p = imacro->argument[nargs].token;
+                       }
+                       else
+                       {
+                               *p++ = *tok++;
+                       }
                }
 
-               // Allocate space for argument ptrs and so on and then go back and
-               // construct the arg frame
-               if (dry_run)
-               {
-                       if (nargs != 0)
-//Barfing here with memory corruption in glibc. TOKEN is defined as LONG, which is uint32_t
-//                             p = (TOKEN *)malloc(arg_siz + 1);
-                               p = (TOKEN *)malloc(arg_siz + sizeof(TOKEN));
-
-                       argptr = (TOKEN **)malloc((nargs + 1) * sizeof(LONG));
-                       *argptr++ = (TOKEN *)argp;
-                       argp = argptr;
-               }
-               else 
-                       break;
+               // Make sure to stuff the final EOL (otherwise, it will be skipped)
+               *p++ = EOL;
+               nargs++;
        }
 
-       // 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;
+       // 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_siz = siz;
+       imacro->im_nextln = mac->lineList;
        imacro->im_olduniq = curuniq;
        curuniq = macuniq++;
-/*IMACRO {
-       IMACRO * im_link;               // Pointer to ancient IMACROs
-       LONG * im_nextln;               // Next line to include
-       WORD im_nargs;                  // # of arguments supplied on invocation
-       WORD im_siz;                    // Size suffix supplied on invocation
-       LONG im_olduniq;                // Old value of 'macuniq'
-       SYM * im_macro;                 // Pointer to macro we're in
-       char im_lnbuf[LNSIZ];   // Line buffer
-};*/
 
        DEBUG
        {
-               printf("nargs=%d\n", nargs);
+               printf("# args = %d\n", nargs);
 
-               for(nargs=0; nargs<imacro->im_nargs; ++nargs)
+               for(uint16_t i=0; i<nargs; i++)
                {
-                       printf("arg%d=", nargs);
-                       dumptok(argp[imacro->im_nargs - nargs - 1]);
+                       printf("arg%d=", i);
+                       DumpTokens(imacro->argument[i].token);
                }
        }
 
        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);
-}