home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / nasm20b / nasm_src / macro.c < prev    next >
C/C++ Source or Header  |  1993-01-19  |  14KB  |  493 lines

  1. /* ---------------------------------------------------------------------- */
  2. /*                   Copyright (C) 1991 by Natürlich!                     */
  3. /*                      This file is copyrighted!                         */
  4. /*                Refer to the documentation for details.                 */
  5. /* ---------------------------------------------------------------------- */
  6. #define DEBUG  0
  7. #define LOCALDEBUG  DEBUG
  8. #include <stdio.h>
  9. #include "defines.h"
  10. #include "nasm.h"
  11. #include "y_tab.h"
  12. #include "labels.h"
  13. #include "debug.h"
  14. #include <setjmp.h>
  15. #include "buffer.h"
  16. #if VERSION
  17. #include "inputfst.h"
  18. #include "exprfast.h"
  19. #endif
  20. #include OSBIND
  21. #include NMALLOC_H
  22. #include "code.h"
  23.  
  24. #define MB_SIZE   (sizeof( buffer) + sizeof( macro))
  25. #define NIL   ((char *) 0)
  26.  
  27. #if __NSTDC__ && TURBO
  28. static void    mac_done( buffer huge *),
  29.                lxsyntax( char *);
  30. static int     mac_get( void),
  31.                *more_space( void);
  32. extern int     (*gettoken)(void);
  33. #else
  34. static void    mac_done(),
  35.                lxsyntax();
  36. static int     mac_get( void);
  37. extern int     (*gettoken)();
  38. #endif
  39.  
  40.  
  41. static macro huge *header[SEP],  huge *tailer[SEP],  huge *rover;
  42. extern char       is_where[], ovf_loss[];
  43. int               freshflag = 1,
  44.                   _call_macro;
  45. extern char       c;
  46. extern jmp_buf    syn_panic;
  47.  
  48.  
  49. #if DEBUG
  50. #if LOCALDEBUG
  51. int         syndebug;
  52. #else
  53. extern int  syndebug;
  54. #endif
  55. #endif
  56.  
  57. extern int           _in_if, show_expansion, show_mload;
  58. extern lword         yylval, l_hash;
  59. extern buffer huge   *bp, huge *hp;
  60. int                  used, _in_macro;
  61.  
  62.  
  63. /* ---------------------------------------------------------- */
  64. /* This is a rather wasteful, but nevertheless _fast_ way of  */
  65. /* Sucking in macros. Only once, when the boundary has been   */
  66. /* crossed, there is a need to copy over stuff.               */
  67. /* ---------------------------------------------------------- */
  68. typedef struct mac_m_
  69. {
  70.    int huge             *s;
  71.    struct mac_m_ huge   *before;
  72. } mac_m;
  73.  
  74. static mac_m huge *c_h;
  75. word              tok_remain;
  76. static int huge   *start;      /* points to the beginning of macro */
  77.  
  78.  
  79. static int   *more_space()
  80. {
  81.    register mac_m huge  *p;
  82.    register lword       rem;
  83. #if STATISTICS
  84.    extern word       _m_macro;
  85.    extern lword      _s_macro;
  86.    _m_macro++;
  87.    _s_macro = MACSPACE + sizeof( mac_m);
  88. #endif
  89.  
  90.    ENTER("more_space");
  91.    p    = (mac_m huge *) nmalloc( MACSPACE + sizeof( mac_m));
  92.    p->s = (int *) ((char huge *) p + sizeof( mac_m));
  93.    if( ! (p->before = (mac_m huge *) c_h))                /* First time ?? */
  94.    {
  95.       c_h = p;
  96.       tok_remain = MACTOKMAX;
  97.       LEAVE();
  98.       return( start = p->s);
  99.    }
  100. #if ! VERSION
  101.    if( (size_t) ((char huge *) c_h->s + MACSPACE - (char huge *) start) !=
  102.        (lword)  ((char huge *) c_h->s + MACSPACE - (char huge *) start))
  103.       nierror("Conversion did indeed lose some bytes in MACRO.C:more_space");
  104. #endif
  105.    if( start == c_h->s)
  106.       nferror("ONE macro can't possibly be THAT long!");
  107.    bcopy( start, p->s,
  108.          rem = (lword) ((char huge *) c_h->s + MACSPACE - (char huge *) start));
  109.  
  110.    tok_remain = (word) ((MACSPACE - rem) / (sizeof( int) + sizeof( lword)));
  111.    c_h = p;
  112.    LEAVE();
  113.    return( (int *) ((char huge *) (start = p->s) + rem));
  114. }
  115.  
  116. /* ---------------------------------------------------------- */
  117. /*          Functions to suck in a macro and store it.        */
  118. /*   HIDE your register variables, if a LONGJMP is about to   */
  119. /*   happen. Therefore no and remain are static outside.      */
  120. /* ---------------------------------------------------------- */
  121. static unsigned    no = 0;          /* bc/o LONGJMPs          */
  122. void   load_macro( name)
  123. char  *name;
  124. {
  125.    register int         tok;
  126.    register int huge    *s = start;
  127.  
  128.    ENTER("load_macro");
  129.    no = 0;
  130.    freshflag = 1;                                  /* new yylex caller */
  131.    if( find_macro( name))
  132.    {
  133.       nerror("This old assembler can't handle macro redefinitions, so you better choose another name");
  134.       while( (tok = yylex()) && tok != T_ENDM);
  135.       if( ! tok)
  136.          nferror("Reached end of file while skipping to .ENDM");
  137.       return;
  138.    }
  139.    if( (tok = yylex()) != T_EOL)
  140.    {
  141.       nwarning("Garbage after .macro <name> definition!");
  142.       while( (tok = yylex()) != T_EOL);
  143.    }
  144.    inc_line();
  145.    if( show_mload)
  146.       printf("Loading macro definition \"%s\"\n", name);
  147.  
  148.    for(;;)
  149.    {
  150.       switch( tok = yylex())
  151.       {
  152.          case 0         :
  153.             MESS("Case 0");
  154.             nferror("Reached end of file before an .ENDM");
  155.  
  156.          case T_MACRO   :
  157.             MESS("Case T_MACRO");
  158.             nerror("U can't define a macro in a macro, ignoring until .ENDM");
  159.             while( (tok = yylex()) && tok != T_ENDM);
  160.             if( ! tok)
  161.                nferror("...unfortunately that doesn't exist");
  162.             break;
  163.  
  164.          case T_ENDM    :
  165.             MESS("Case T_ENDM");
  166.          {
  167.             register buffer huge *p;
  168.             register macro  huge *q;
  169.  
  170.             p = (buffer huge *) nmalloc( (long) MB_SIZE);
  171.             q = (macro huge *) ((char huge *) p + sizeof( buffer));
  172.             p->buflist   = p->p = (byte *) start;
  173.             p->name      = name;
  174.             p->remain    = p->oremain = no;
  175.             p->type      = BUF_ALLOC | BUF_TOKEN | BUF_MACRO;
  176.             p->multi.fill= (void (*)(buffer *)) dummy;   /* **-PORT #1-**/
  177.             p->done      = mac_done;
  178.             p->get       = (int (*)()) mac_get;          /* **-PORT #1-**/
  179.             MESS("Filling q");
  180.             q->name      = p->name = name;
  181.             q->hash      = l_hash;
  182.             q->buf       = p;
  183.             q->inuse     = p->line = 0;
  184.             MESS("Linking in...");
  185.             einlinker( header, tailer, rover, used, q);
  186.             start        = (int huge *) s;
  187.             freshflag    = 1;           /* a new yylex caller will appear */
  188.             LEAVE();
  189.             return;
  190.          }
  191.  
  192.          case T_INCLUDE :
  193.             MESS("T_INCLUDE");
  194.             if( ! (tok = yylex()))
  195.                nferror("Unexpected EOF in the middle of a macro definition");
  196.             if( tok != T_FILE)
  197.                nerror("Valid file specifier expected after .INCLUDE");
  198.                      include( (char *) yylval, ".s65");
  199.             if( (tok = yylex()) != T_EOL)
  200.             {
  201.                nwarning("Garbage after .include <file> definition!");
  202.                while( (tok = yylex()) != T_EOL);
  203.             }
  204.             break;
  205.  
  206.          default        :
  207.             while( ! tok_remain--)
  208.                s = more_space();
  209.             if( (*s++ = tok) == T_EOL)
  210.                bp->line++;
  211.             *(lword huge *)s = yylval;
  212.             s += sizeof( lword) / sizeof( int);
  213.             no++;
  214.       }
  215.    }
  216. }
  217.  
  218.  
  219. #if DEBUG
  220. #define fdreturn( val)  \
  221. {                       \
  222.    int   foo = (val);   \
  223.                         \
  224.    prtname( foo);       \
  225.    LEAVE();             \
  226.    return( foo);        \
  227. }
  228. #else
  229. #define fdreturn     return
  230. #endif
  231.  
  232. static int  mac_get()
  233. {
  234.    static int           tok;
  235.    register buffer huge *P = bp;
  236.  
  237.    ENTER("mac_get");
  238.    if( freshflag)                /* Have we set syn_panic already ??    */
  239.    {
  240.       freshflag = 0;             /* No clr flag                         */
  241. #if DEBUG
  242.       SAVESTATE( &syndebug);
  243. #endif
  244.       if( setjmp( syn_panic))    /* Do the setjmp ONCE                  */
  245.       {
  246.          int foo;
  247. #if DEBUG
  248.          SETBACK(syndebug);
  249. #endif
  250.          MESS("\007\t\tsyntax panic occurred");
  251.          while( P->remain--)                 /* Something left ?        */
  252.          {
  253.             foo   = *(int huge *)P->p;
  254.             P->p += sizeof( int) + sizeof( lword);
  255.             if( foo)
  256.                break;
  257.          }
  258.       }
  259.    }
  260.    if( P->remain--)                    /* Something left ?    */
  261.    {
  262. #if ! PHILOSOPHICAL_PROBLEM
  263.       tok    = *((int huge *) P->p)++;
  264.       yylval = *((lword huge *) P->p)++;
  265. #else
  266.       tok    = *(int huge *) P->p;
  267.       P->p   = (void huge *) ((int *) P->p + 1);
  268.       yylval = *(lword huge *) P->p;
  269.       P->p   = (void huge *) ((lword huge *) P->p + 1);
  270. #endif
  271.       if( tok < HIGHEST || _in_if)     /* not a parameter ??   */
  272.          fdreturn( tok);               /* then return that     */
  273.       {
  274.          register lexpr huge  *l;
  275.  
  276.          if( tok >= T_MLPARA)
  277.          {
  278.             register label huge  *q;
  279.  
  280.             MESS("Using the label indirection");
  281.             if( ! (q = find_label( (char huge *) yylval)) || q->refs)
  282.               lxsyntax("Foward references of macro indices. Tsk Tsk");
  283.             yylval = (lword) q->val;
  284.          }
  285.          if( yylval > P->parms.list->expr->val)
  286.             lxsyntax("Missing macro parameter error");
  287.          l = lex_get( P->parms.list, (word) yylval);
  288.          if( _call_macro)
  289.          {
  290.             yylval = (lword) l;
  291.             return( T_PARA);
  292.          }
  293.          
  294.          if( (tok & 1) == (T_MSPARA & 1))                /* OPTIMIZE */
  295.          {
  296.             yylval = (lword) l->string;
  297.             IMESS("Supplying $%lx as string value", yylval, 4);
  298.             fdreturn( T_STRING);
  299.          }
  300.          l = (lexpr huge *) l->expr;
  301.          yylval = (lword) copyexpr( (expr *) l);
  302. /*         ((expr *)yylval)->fix = 0;      */              /* That true ? */
  303.          IMESS("Supplying $%lx for an expression", yylval, 4);
  304.          fdreturn( T_EXPR);
  305.       }
  306.    }
  307. #if DEBUG
  308.    dump_buffer( bp);
  309. #endif
  310.    MESS("Killing buffer");
  311.    kill_buffer( hp);                   /* Install new buffer      */
  312. #if DEBUG
  313.    dump_buffer( bp);
  314. #endif
  315.    fdreturn( T_EOL);
  316. }
  317.  
  318.  
  319. macro *find_macro( s)
  320. register char  *s;
  321. {
  322.    register macro huge  *p;
  323.    register lword       hash;
  324.    register int         res;
  325.  
  326.    ENTER("find_macro");
  327.    IMESS("Looking for \"%s\"", (lword) s, 4);
  328.    l_hash = hash = calc_hash( s + 1);
  329.    p = header[ used = is_where[*s]];
  330.    while( p && (p->hash < hash ||
  331.           (p->hash == hash && (res = strcmp( p->name, s)) < 0)))
  332.       p = p->next;
  333.    rover = p;
  334.  
  335.    if( ! found( p, hash) || res)  /* if not found or at end of table */
  336.    {
  337.       LEAVE();
  338.       return( 0);
  339.    }
  340.    LEAVE();
  341.    return( p);
  342. }
  343.  
  344.  
  345. void  do_macro( name, lex)
  346. char        *name;
  347. lexpr huge  *lex;
  348. {
  349.    register macro huge  *q;
  350.    register buffer huge *p;
  351.    int                  flag = __p - __program >= MAXMODULE;
  352.  
  353.    ENTER("do_macro");
  354.    IMESS("Executing macro \"%s\"", (lword) name, 4);
  355.    if( q = find_macro( name))
  356.    {
  357.       lex->string = make_string( name);      /* ARGH! make that better */
  358.       if( ! q->buf->oremain)
  359.       {
  360.          LEAVE();
  361.          return;
  362.       }
  363.       if( q->inuse)
  364.       {
  365.          MESS("q seems to be in use");
  366.                 if( q->inuse == 1)
  367.                  nwarning("Macro recursion (allowed but maybe unwanted)");
  368.          if( flag)
  369.             nferror("Probably a macro recursion caused the code buffer\
  370.  overflow");
  371.          p          = (buffer huge *) nmalloc( (long) sizeof( buffer));
  372.          bcopy((char *) q->buf, (char *) p, (long) sizeof( buffer));
  373.          p->buflist = p->p = q->buf->buflist;
  374.          p->remain  = p->oremain;
  375.          p->name    = q->name;
  376.          p->type    = BUF_MACRO | BUF_TOKEN | BUF_FREE | BUF_ALLOC;
  377.       }
  378.       else
  379.          p = q->buf;
  380.  
  381.       if( flag)
  382.          nferror( ovf_loss);
  383.  
  384.       q->inuse++;
  385.       IMESS("p->remain = %ld", p->remain, 4);
  386.       if( (p->before = bp))
  387.       {
  388.          bp->next = p;
  389. /*         if( ! (bp->type & BUF_TOKEN))
  390.             bp->_aux2  = c;
  391. */
  392.       }
  393.       p->multi.dad  = q;
  394.       p->parms.list = lex;
  395.       p->line       = 0;
  396.       p->next       = 0;
  397.       p->get        = (int (*)()) (gettoken = mac_get); /* **-PORT #1-**/
  398.       p->done       = mac_done;
  399.       bp            = p;
  400.       MESS("MACRO has been linked into buffer list");
  401. #if DEBUG
  402.       dump_buffer( bp);
  403. #endif
  404.       freshflag     = 1;
  405.       _in_macro++;
  406.  
  407.       if( show_expansion)
  408.       {
  409.          int    i = 1;
  410.          
  411.          tabout();
  412.          printf( "line %4.4d, expanding macro: \"%s\"\n", 
  413.                 p->before->line, name);
  414.          tab();
  415.          printf( "\t#parameters : %d\n", lex->expr->val);
  416.          
  417.          while( lex = lex->next)
  418.          {
  419.             tab();
  420.             printf("\t%%%d : %c $%04X   %%$%d : \"%s\"\n", 
  421.                    i,
  422.                    valued( lex->expr) ? ' ' : 'F',
  423.                    lex->expr->val,
  424.                    i,
  425.                    lex->string + 2);
  426.             i++;
  427.          }
  428.       }
  429.    }
  430.    else
  431.       nserror( "Macro is undefined", name);
  432.    LEAVE();
  433. }
  434.  
  435.  
  436. void  call_macro( s)
  437. char     *s;
  438. {
  439.    nwarning("unimplemented directive");
  440. /* 
  441.    if( bp->type & BUF_MACRO)
  442.       do_macro( s, slex_ch( lex_pl( NIL, bp->parms.list->expr), 
  443.                            bp->parms.list->next));
  444.    else
  445.       nerror("You can use .CALL only in macro definitions");
  446. */
  447. }
  448.  
  449.  
  450. void  rept_macro( ex, name, lex)
  451. expr huge   *ex;
  452. char        *name;
  453. lexpr huge  *lex;
  454. {
  455.    if( unvalued( ex))
  456.       nerror("No foward references for repeat factor allowed");
  457.    else
  458.    {
  459.       word  i;
  460.  
  461.       for( i = ex->val; i; i--)
  462.          do_macro( name, lex);
  463.    }
  464. }
  465.  
  466. static void   mac_done( p)
  467. register buffer huge *p;
  468. {
  469.    ENTER("mac_done");
  470.    p->line   = 0;
  471.    p->p      = p->buflist;
  472.    p->remain = p->oremain;
  473.    p->multi.dad->inuse--;                  /* incomplete */
  474.    _in_macro--;                            /* (later: ;) */
  475.    if( show_expansion)
  476.    {
  477.         tabin();
  478.         printf( "Done with macro: \"%s\"\n", p->name);
  479.    }
  480.    LEAVE();
  481. }
  482.  
  483.  
  484. static void    lxsyntax( err)
  485. char  *err;
  486. {
  487.    nerror( err);
  488.    longjmp( syn_panic, 1);
  489. }
  490.  
  491. /* ; Huh? What? Why?? Tell me more... I don't see the problem */
  492.  
  493.