home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / nasm20b / nasm_src / lexer.c < prev    next >
C/C++ Source or Header  |  1993-01-19  |  34KB  |  1,273 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 TOKDEBUG  0            /* following set 4 Atari 8MHz */
  8. #define FINPUT_IO 1            /* yields 15% speed increase  */
  9. #define QINPUT_IO 1            /* yields 20% speed increase  */
  10. #define USEINLINE 0
  11. #define QSTRING   0            /* 1 == doesn't do much       */
  12. #define QWHITE    1
  13. #define QCOMMENT  1
  14. #define QIDENT    1
  15. #define QIDENT2   0            /* 1 == worsens performance ! */
  16. #define QLABEL    0            /* 1 == doesn't do anything   */
  17. #define QMACRO    0            /* 1 == same or worse         */
  18. #define QDIRECT   0            /* 1 == doesn't do anything   */
  19.  
  20. /* --------------------------------------------------------- */
  21. /*    SHIT!! FLEX can't digest characters >= 128             */
  22. /*    Now I have to write my own lexer...                    */
  23. /* --------------------------------------------------------- */
  24. #include "defines.h"
  25. #include "nasm.h"
  26. #include "y_tab.h"
  27. #include <stdio.h>
  28. #if OS == TOS
  29. #include <osbind.h>
  30. #endif
  31. #include <setjmp.h>
  32.  
  33. #include "debug.h"
  34. #include "code.h"
  35. #include NMALLOC_H
  36. #if VERSION && FINPUT_IO
  37. extern buffer huge   *bp;
  38. # include "inputfst.h"
  39. #endif
  40.  
  41. #define LINESTART       0
  42. #define INSTRUCTION     1
  43. #define AFTERINSTR      2
  44. #define AFTERELSE       3
  45. #define AFTEROPTION     4
  46. #define AFTERFLOAT      5
  47. #define AFTERINCLUDE    6
  48. #define COMMENT         7
  49.  
  50. #define E_GARBAGE    garbage        /* historic */
  51. #define E_LABELFORM  labelform
  52. #define E_HEXLEN     hexlen
  53. #define E_INTSIZE    intsize
  54.  
  55. static char
  56.    igarbage[] =  "Garbage in the instruction field",
  57.    garbage[]  =  "Totally uncomprehendable garbage",
  58.    labelform[] = "Label starts off with wrong character",
  59.    hexlen[] =  "Hex value exceeds 16 Bit (not that good on a 64K machine)",
  60.    intsize[] = "Integer value >= 65536, how would that fit into 2 bytes ?",
  61.    mpara_incomplete[] = 
  62.                 "Incomplete macro parameter (form %[$]<[0-9]+|(<label>))";
  63.  
  64. /* --------------------------------------------------------- */
  65. /* The ultra-clever (har har) way of deciding whether we are */
  66. /* facing something usable as an identifier character.       */
  67. /* There is a method to this madness:                        */
  68. /*   Bit7 . Bit6 . Bit5 . Bit4 . Bit3 . Bit2 . Bit1 . Bit0   */
  69. /*   -----+------+------+------+------+------+------+-----   */
  70. /*   Lower|      |      | Foo  | A-Z  |Float | Hex  | No     */
  71. /*   -----+------+------+------+------+------+------+-----   */
  72. /*    $80   $40    $20    $10    $08    $04    $02    $01    */
  73. /*                                                           */
  74. /*    A question remains, are we losing with this table ??   */
  75. /* --------------------------------------------------------- */
  76. #define is_ident( c)    (is_what[ (c)])
  77. #define is_lower( c)    ((signed char) is_what[ (c)] < 0)
  78. #define is_hex( c)      (is_what[ (c)] & M_HEX)
  79. #define is_digit( c)    (is_what[ (c)] == DIGIT)
  80. #define is_letter( c)   (is_what[ (c)] & M_LETTER)
  81. #define is_float( c)    (is_what[ (c)] & M_FLOAT)
  82.  
  83. #define tis_ident( c)   (p_table[ (c)])
  84. #define tis_lower( c)   ((signed char) p_table[ (c)] < 0)
  85. #define tis_hex( c)     (p_table[ (c)] & M_HEX)
  86. #define tis_digit( c)   (p_table[ (c)] == DIGIT)
  87. #define tis_letter( c)  (p_table[ (c)] & M_LETTER)
  88. #define tis_float( c)   (p_table[ (c)] & M_FLOAT)
  89.  
  90. #define M_LOWER   0x80
  91. #define M_FOO     0x10
  92. #define M_LETTER  0x08
  93. #define M_FLOAT   0x04
  94. #define M_HEX     0x02
  95. #define M_DIGIT   0x01
  96.  
  97. #define DIGIT     (M_DIGIT  | M_HEX | M_FLOAT)
  98. #define L         (M_LETTER | M_LOWER)           /* lower  */
  99. #define A          M_LETTER                      /* upper  */
  100. #define H         (M_LETTER | M_HEX)             /* up&hex */
  101. #define E         (M_LETTER | M_HEX | M_FLOAT)
  102. #define P                             M_FLOAT
  103. #define X          M_FOO
  104. #define N          DIGIT
  105.  
  106.  
  107. byte is_what[] =                          /* xlat:  is' watt !?!? */
  108. {
  109.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $00 */
  110.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $10 */
  111.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,P,0, /* $20 */
  112.    N,N,N,N,  N,N,N,N,  N,N,X,0,  0,0,0,X, /* $30 */
  113.  
  114.    X,H,H,H,  H,E,H,A,  A,A,A,A,  A,A,A,A, /* $40 */
  115.    A,A,A,A,  A,A,A,A,  A,A,A,0,  0,0,0,X, /* $50 */
  116.    0,L,L,L,  L,L,L,L,  L,L,L,L,  L,L,L,L, /* $60 */
  117.    L,L,L,L,  L,L,L,L,  L,L,L,0,  0,0,0,0, /* $70 */
  118.  
  119.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $80 */
  120.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $90 */
  121.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $A0 */
  122.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $B0 */
  123.  
  124.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $C0 */
  125.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $D0 */
  126.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $E0 */
  127.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0  /* $F0 */
  128. };
  129.  
  130. #undef F
  131. #undef N
  132. #undef L
  133. #undef A
  134. #undef H
  135. #undef E
  136. #undef P
  137. #undef X
  138.  
  139.  
  140. #define is_white( c)    (white[ (c)])
  141. #define skip_white(c)   while( white[ c]) c = uinput()
  142. #define tis_white( c)   (p_table[ (c)])
  143. #define tskip_white(c)  while( p_table[ c]) c = uinput()
  144.  
  145. static char white[] =         /* ain't no saying whether this actually */
  146. {                             /* helps improve the speed               */
  147.    0,0,0,0,  0,0,0,0,  0,1,0,0,  0,1,0,0, /* $00 */
  148.    0,0,0,0,  0,0,0,0,  0,0,1,0,  0,0,0,0, /* $10 */   /* $1A for MSDOS */
  149.    1,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $20 */   /* whatever that */
  150.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $30 */   /* might be      */
  151.  
  152.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $40 */
  153.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $50 */
  154.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $60 */
  155.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $70 */
  156.  
  157.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $80 */
  158.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $90 */
  159.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $A0 */
  160.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $B0 */
  161.  
  162.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $C0 */
  163.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $D0 */
  164.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $E0 */
  165.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0  /* $F0 */
  166. };
  167.  
  168. #define A   0x01   /* 'X'  */
  169. #define B   0x02   /* 'Y'  */
  170.  
  171. #define C   0x03   /* '#'  */
  172.  
  173. #define D   0x04   /* '('  */
  174. #define E   0x05   /* ')'  */
  175. #define F   0x06   /* ','  */
  176. #define G   0x07   /* '='  */
  177. #define H   0x08   /* '+'  */
  178. #define I   0x09   /* '-'  */
  179. #define J   0x0A   /* '!'  */
  180. #define K   0x0B   /* '&'  */
  181. #define L   0x0C   /* '*'  */
  182. #define M   0x0D   /* '/'  */
  183. #define N   0x0E   /* '\\' */
  184. #define O   0x0F   /* '^'  */
  185. #define P   0x10   /* '['  */
  186. #define Q   0x11   /* ']'  */
  187. #define IREGS  0x02
  188.  
  189. static byte af1_toks[] =
  190. {
  191.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $00 */
  192.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $10 */
  193.    0,J,0,C,  0,0,K,0,  D,E,L,H,  F,I,0,M, /* $20 */
  194.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,G,0,0, /* $30 */
  195.  
  196.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $40 */
  197.    0,0,0,0,  0,0,0,0,  A,B,0,P,  N,Q,O,0, /* $50 */
  198.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $60 */
  199.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $70 */
  200.  
  201.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $80 */
  202.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $90 */
  203.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $A0 */
  204.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $B0 */
  205.  
  206.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $C0 */
  207.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $D0 */
  208.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $E0 */
  209.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0  /* $F0 */
  210. };
  211.  
  212. static byte af2_toks[] =
  213. {
  214.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $00 */
  215.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $10 */
  216.    0,J,0,0,  0,0,K,0,  D,E,L,H,  F,I,0,M, /* $20 */
  217.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,G,0,0, /* $30 */
  218.  
  219.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $40 */
  220.    0,0,0,0,  0,0,0,0,  0,0,0,P,  N,Q,O,0, /* $50 */
  221.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $60 */
  222.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $70 */
  223.  
  224.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $80 */
  225.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $90 */
  226.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $A0 */
  227.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $B0 */
  228.  
  229.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $C0 */
  230.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $D0 */
  231.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0, /* $E0 */
  232.    0,0,0,0,  0,0,0,0,  0,0,0,0,  0,0,0,0  /* $F0 */
  233. };
  234. #undef A
  235. #undef B
  236. #undef C
  237. #undef D
  238. #undef E
  239. #undef F
  240. #undef G
  241. #undef H
  242. #undef I
  243. #undef J
  244. #undef K
  245. #undef L
  246. #undef M
  247. #undef N
  248. #undef O
  249. #undef P
  250. #undef Q
  251.  
  252.  
  253. #if DEBUG        /* Bugs ? Yeah SURE we gottem.. All sizes and shapes! */
  254. #define dreturn( val)   \
  255. {                       \
  256.    int   foo = (val);   \
  257.    prtname( foo);       \
  258.    LEAVE();             \
  259.    return( foo);        \
  260. }
  261.  
  262. #define xreturn( val)   \
  263. {                       \
  264.    int   foo = (val);   \
  265.                         \
  266.    LEAVE();             \
  267.    return( foo);        \
  268. }
  269.  
  270. #define fdreturn( val)  \
  271. {                       \
  272.    int   foo = (val);   \
  273.                         \
  274.    c = uinput();        \
  275.    prtname( foo);       \
  276.    LEAVE();             \
  277.    return( foo);        \
  278. }
  279.  
  280. #else
  281. #define dreturn   return
  282. #define xreturn   return
  283. #define fdreturn( val)  \
  284. {                       \
  285.    c = uinput();        \
  286.    return( val);        \
  287. }
  288. #endif
  289.  
  290. #define comparators()                                 \
  291.    if( c_ == '<')                                     \
  292.       if( (c_ = uinput()) == '>')                     \
  293.       {                                               \
  294.          c = c_;                                      \
  295.          fdreturn( T_NEQ);                            \
  296.       }                                               \
  297.       else                                            \
  298.          if( (c = c_) == '=')                         \
  299.          {                                            \
  300.             fdreturn( T_LEQ);                         \
  301.          }                                            \
  302.          else                                         \
  303.             dreturn( '<');                            \
  304.                                                       \
  305.    if( c_ == '>')                                     \
  306.    {                                                  \
  307.       if( (c = uinput()) == '=')                      \
  308.       {                                               \
  309.          fdreturn( T_GEQ);                            \
  310.       }                                               \
  311.       dreturn( '>');                                  \
  312.    }
  313.  
  314. extern lword yylval;
  315. extern       freshflag;
  316.  
  317. static char  miss_char[] = "Missing character after \' (quote)",
  318.              yytext[1024];
  319. int          state = LINESTART,
  320.              wasstrlen,
  321. #if __NSTDC__
  322.              (*gettoken)( void);
  323. #else
  324.              (*gettoken)();
  325. #endif
  326.  
  327. byte         c;
  328. #if VERSION
  329. static byte  tmp;
  330. #endif
  331. jmp_buf      syn_panic;
  332.  
  333. #if DEBUG
  334. int          syndebug;
  335. #endif
  336.  
  337.  
  338. int   nilexer()
  339. {
  340.    yylval = 0;
  341.    return(0);
  342. }
  343.  
  344.  
  345. int   yylex()
  346. {
  347.    ENTER("yylex");
  348. #if TOKDEBUG
  349.    {
  350.       int   i = (*gettoken)();
  351.  
  352.       prtname( i);
  353.       xreturn( i);
  354.    }
  355. #else
  356. # if OS == TOS && WITHNOISY
  357.    {
  358.       extern int  noisytok, _in_macro;
  359.  
  360.       if( noisytok)
  361.       {
  362.          static unsigned char fx[] =
  363.          {
  364.             2, 0, 3, 0, 9, 8, 7, 0xFD, 0xFF, 10,
  365.             7, 0xFF, 0xFF, 0
  366.          };
  367.          int          tok = (*gettoken)();
  368.  
  369.  
  370.          fx[1] = tok & 0x3F;
  371.          fx[3] = _in_macro;
  372.          Dosound( fx);
  373.          xreturn( tok);
  374.       }
  375.    }
  376. # endif
  377.    xreturn((*gettoken)());
  378. #endif
  379. }
  380.  
  381.  
  382. int   lexer()
  383. {
  384.    register byte  c_ = c,
  385.                   *p_table = (byte *) white;
  386.  
  387.    ENTER( "lexer");
  388.    if( freshflag)                /* Have we set syn_panic already ??    */
  389.    {
  390.       freshflag = 0;             /* No clr flag                         */
  391. #if DEBUG
  392.       SAVESTATE( &syndebug);
  393. #endif
  394.       if( setjmp( syn_panic))    /* Do the setjmp ONCE                  */
  395.       {
  396. #if DEBUG
  397.          SETBACK( syndebug);
  398. #endif
  399.          MESS("\007\t\tsyntax panic occurred");
  400.          while( c_ != '\n')       /* If a longjmp() happens: ignore line */
  401.             c_ = uinput();
  402.         state = LINESTART;       /* reset state */
  403.       }
  404.    }
  405.  
  406.  
  407.    if( tis_white( c_))             /* TOS files have white before LF */
  408.    {
  409. #if VERSION && FINPUT_IO && QINPUT_IO && QWHITE
  410.       register byte huge   *pt  = bp->p;
  411.       register byte        *tab = _uptable;
  412.       register lword       rem  = bp->remain;
  413.  
  414.       while( tis_white( c_ = quinput( rem, pt, tab)));
  415.       if( bp)
  416.       {
  417.          bp->remain = rem;
  418.          bp->p      = pt;
  419.       }
  420. #else
  421.       while( tis_white( c_ = uinput()));
  422. #endif
  423.       if( state == LINESTART)
  424.          state = INSTRUCTION;
  425.    }
  426.  
  427.    if( c_ == ';' || state == COMMENT)
  428.    {
  429. #if VERSION && FINPUT_IO && QINPUT_IO && QCOMMENT
  430.       register byte huge   *pt = bp->p;
  431.       register byte       *tab = _uptable;
  432.       register lword       rem = bp->remain;
  433.  
  434.       while( (c_ = quinput( rem, pt, tab)) != '\n');
  435.       if( bp)
  436.       {
  437.          bp->remain = rem;
  438.          bp->p      = pt;
  439.       }
  440. #else
  441.       while( (c_ = uinput()) != '\n');
  442. #endif
  443.    }
  444.  
  445.    if( c_ == '\n')
  446.    {
  447.       state = LINESTART;
  448.       c = c_;
  449.       fdreturn( T_EOL);
  450.    }
  451.  
  452. #if USEINLINE
  453.    switch( state)
  454.    {
  455.       case LINESTART    :
  456.          IMESS("[LINESTART] c == %d", (lword) c_, 2);
  457.          state = INSTRUCTION;
  458.          if( is_ident( c = c_))
  459.          {
  460.             xreturn( label_suckin());
  461.          }
  462.          else
  463.             junk_suckin( E_GARBAGE);
  464.  
  465.  
  466.       case INSTRUCTION  :
  467.          IMESS("[INSTRUCTION c=='%c']", (lword) c_, 1);
  468.          if( c_ == '.')
  469.          {
  470.             c = c_;
  471.             state = AFTERELSE;
  472.             xreturn( directive_suckin());
  473.          }
  474.          if( is_ident( c = c_))
  475.          {
  476.             state = AFTERINSTR;
  477.             xreturn( macro_suckin()); /* macros and instructions too */
  478.          }
  479.          state = AFTERELSE;
  480.          if( c_ == '=')
  481.             fdreturn( c_);
  482.          if( c_ == '*')
  483.          {
  484.             while( tis_white( c_ = uinput()));
  485.             if( c_ == '=')
  486.                fdreturn( T_ORG);
  487.             c_ = '*';
  488.          }
  489.          yytext[0] = c = c_;
  490.          yytext[1] = 0;
  491.          lsyntax( igarbage);
  492.  
  493.  
  494.       case AFTERINSTR   :
  495.          MESS("[AFTERINSTR]");
  496.          switch( c_)
  497.          {
  498.             case '$' :  xreturn( hex_suckin());
  499.             case '.' :  xreturn( directive_suckin());
  500.             case '%' :  xreturn( para_suckin());
  501.             case '\'':
  502.             {
  503.                if( tis_white( c = input()))
  504.                   lsyntax(miss_char);
  505.                yylval = (lword) c;
  506.                fdreturn( T_CHAR);
  507.             }
  508.          }
  509.          if( is_digit( c = c_))
  510.             xreturn( int_suckin());
  511.          {
  512.             register int   a;
  513.  
  514.             if( a = af1_toks[ c_])
  515.             {
  516.                if( is_ident( c = uinput()) && a <= IREGS)
  517.                   xreturn( ident2_suckin( c_));
  518.                dreturn( c_);
  519.             }
  520.          }
  521.          if( is_ident( c_))
  522.             xreturn( ident_suckin());
  523.          comparators();
  524.          junk_suckin( garbage);
  525.  
  526.  
  527.       case AFTERELSE    :
  528.          MESS("[AFTERELSE]");
  529.          switch( c_)
  530.          {
  531.             case '%' :  xreturn( para_suckin());
  532.             case '"' :  xreturn( string_suckin());
  533.             case '$' :  xreturn( hex_suckin());
  534.             case '.' :  xreturn( directive_suckin());
  535.             case '\'':  if( tiswhite( c = input()))
  536.                            lsyntax(miss_char);
  537.                         yylval = (lword) c;
  538.                         fdreturn( T_CHAR);
  539.          }
  540.          if( is_digit( c = c_))
  541.             xreturn( int_suckin());
  542.          if( af2_toks[ c_])
  543.             fdreturn( c_);
  544.          if( is_ident(c_))
  545.             xreturn( ident_suckin());
  546.          comparators();
  547.          junk_suckin( garbage);
  548.  
  549.  
  550.       case AFTEROPTION  :
  551.          MESS("[AFTEROPTION]");
  552.          if( c_ == ',')
  553.             fdreturn( c_);
  554.          c = c_;
  555.          xreturn( option_suckin());
  556.  
  557.  
  558.       case AFTERINCLUDE :
  559.          MESS("[AFTERINCLUDE]");
  560.          if( c_ == '#')
  561.             fdreturn( c_);
  562.          c = c_;
  563.          xreturn( file_suckin());
  564.  
  565.       case AFTERFLOAT   :
  566.          MESS("[AFTERFLOAT]");
  567.          if(  c_ == ',')
  568.             fdreturn( c_);
  569.          c = c_;
  570.          xreturn( float_suckin());
  571.    }
  572.    nierror("problems with the lexer state");
  573. }
  574. #else
  575.    switch( state)
  576.    {
  577.       case LINESTART   :
  578.          IMESS("[LINESTART] c == %d", (lword) c, 2);
  579.          state = INSTRUCTION;
  580.          if( is_ident(c = c_))
  581.          {
  582.             xreturn( label_suckin());
  583.          }
  584.          else
  585.             junk_suckin( E_GARBAGE);
  586.  
  587.       case INSTRUCTION :
  588.          IMESS("[INSTRUCTION c=='%c']", (lword) c_, 1);
  589.          if( (c = c_) == '.')
  590.          {
  591.             state = AFTERELSE;
  592.             xreturn( directive_suckin());
  593.          }
  594.          if( is_ident( c))
  595.          {
  596.             state = AFTERINSTR;
  597.             xreturn( macro_suckin()); /* macros and instructions too */
  598.          }
  599.          MESS("**HIT THIS***");
  600.          state = AFTERELSE;
  601.          if( c_ == '=')
  602.             fdreturn( c_);
  603.          if( c_ == '*')
  604.          {
  605.             while( tis_white( c_ = uinput()));
  606.             if( c_ == '=')
  607.                fdreturn( T_ORG);
  608.             c_ = '*';
  609.          }
  610.          yytext[0] = c = c_;
  611.          yytext[1] = 0;
  612.          lsyntax( igarbage);
  613.  
  614.  
  615.       case AFTERINSTR  :
  616.       {
  617.          register int   a;
  618.  
  619.          MESS("[AFTERINSTR]");
  620.          if( a = af1_toks[ c_])
  621.          {
  622.             if( is_ident( c = uinput()) && a <= IREGS)
  623.                xreturn( ident2_suckin( c_));
  624.             dreturn( c_);
  625.          }
  626.          comparators();
  627.          c = c_;
  628.          xreturn( get_itoken());
  629.       }
  630.  
  631.       case AFTERELSE   :
  632.       {
  633.          MESS("[AFTERELSE]");
  634.          if( af2_toks[ c_])
  635.             fdreturn( c_);
  636.          comparators();
  637.          c = c_;
  638.          xreturn( get_etoken());
  639.       }
  640.  
  641.       case AFTEROPTION:
  642.          MESS("[AFTEROPTION]");
  643.          if( c_ == ',')
  644.             fdreturn( c_);
  645.          c = c_;
  646.          xreturn( option_suckin());
  647.  
  648.       case AFTERFLOAT:
  649.          MESS("[AFTERFLOAT]");
  650.          if(  c_ == ',')
  651.             fdreturn( c_);
  652.          c = c_;
  653.          xreturn( float_suckin());
  654.  
  655.       case AFTERINCLUDE:
  656.          MESS("[AFTERINCLUDE]");
  657.          if( c_ == '#')
  658.             fdreturn( c_);
  659.          c = c_;
  660.          xreturn( file_suckin());
  661.    }
  662.    nierror("problems with the lexer state");
  663. #if __NSTDC__ && VERY_PRETTY
  664.    return(0);
  665. #endif
  666. }
  667.  
  668. /* ------------------------------------------------------------- */
  669. /*           Stands for: Get after instruction token.            */
  670. /* ------------------------------------------------------------- */
  671. get_itoken()
  672. {
  673.    ENTER("get_itoken");
  674.    switch( c)
  675.    {
  676.       case '$' :  xreturn( hex_suckin());
  677.       case '.' :  xreturn( directive_suckin());
  678.       case '%' :  xreturn( para_suckin());
  679.       case '\'':  if( is_white( c = input()))
  680.                      lsyntax(miss_char);
  681.                   yylval = (lword) c;
  682.                   fdreturn( T_CHAR);
  683.    }
  684.    if( is_digit(c))
  685.       xreturn( int_suckin());
  686.    if( is_ident( c))
  687.       xreturn( ident_suckin());
  688.    junk_suckin( garbage);
  689. #if __NSTDC__ && VERY_PRETTY
  690.    return(0);
  691. #endif
  692. }
  693.  
  694. /* ------------------------------------------------------------- */
  695. /* Stands for: Get after macro call token.                       */
  696. /* ------------------------------------------------------------- */
  697. get_etoken()
  698. {
  699.    ENTER("get_etoken");
  700.    IMESS("c = '%c'", (lword) c, 1);
  701.    switch( c)
  702.    {
  703.       case '%' :  xreturn( para_suckin());
  704.       case '"' :  xreturn( string_suckin());
  705.       case '$' :  xreturn( hex_suckin());
  706.       case '.' :  xreturn( directive_suckin());
  707.       case '\'':  if( is_white( c = input()))
  708.                      lsyntax(miss_char);
  709.                   yylval = (lword) c;
  710.                   fdreturn( T_CHAR);
  711.    }
  712.    if( is_digit(c))
  713.       xreturn( int_suckin());
  714.    if( is_ident(c))
  715.       xreturn( ident_suckin());
  716.    junk_suckin( garbage);
  717. #if __NSTDC__ && VERY_PRETTY
  718.    return(0);
  719. #endif
  720. }
  721. #endif
  722.  
  723. /* ------------------------------------------------------------- */
  724. /* Stands for: Get after macro call token.                       */
  725. /* ------------------------------------------------------------- */
  726. para_suckin()
  727. {
  728.    ENTER("para_suckin");
  729.  
  730.    switch( c = uinput())
  731.    {
  732.       case '(' :
  733.          MESS("way1a");
  734.          while( is_white( c = uinput()));
  735.          if( is_ident( c))
  736.          {
  737.             MESS("way1b");
  738.             ident_suckin();
  739.             skip_white( c);
  740.             if( c == ')')
  741.                fdreturn( T_MLPARA)
  742.          }
  743.          break;
  744.  
  745.       case '$' :
  746.          MESS("way2a");
  747.          if( is_digit( c = uinput()))
  748.          {
  749.             int_suckin();
  750.             dreturn( T_MSPARA);
  751.          }
  752.          if( c == '(')
  753.          {
  754.             MESS("way2b");
  755.             while( is_white( c = uinput()));
  756.             if( is_ident( c))
  757.             {
  758.                MESS("way2c");
  759.                ident_suckin();
  760.                skip_white( c);
  761.                if( c == ')')
  762.                   fdreturn( T_MLSPARA)
  763.             }
  764.          }
  765.          break;
  766.  
  767.       default :
  768.          IMESS("way3 c = '%c'", (lword) c, 1);
  769.          if( is_digit( c))
  770.          {
  771.             int_suckin();
  772.             dreturn( T_MPARA);
  773.          }
  774.    }
  775.    lsyntax( mpara_incomplete);
  776. }
  777.  
  778.  
  779. ident_suckin()
  780. {
  781.    register byte  *p = (byte *) yytext,
  782.                   c_ = c,
  783.                   *p_table = is_what;
  784.    register int   i = 1;
  785.  
  786.    ENTER("ident_suckin");
  787. #if VERSION && FINPUT_IO && QINPUT_IO && QIDENT
  788.    {
  789.       register byte huge   *pt  = bp->p;
  790.       register byte        *tab = _uptable;
  791.       register lword       rem  = bp->remain;
  792.  
  793.       do
  794.       {
  795.          *p++ = c_;
  796.          i++;
  797.       }
  798.       while( tis_ident( c_ = quinput( rem, pt, tab)));
  799.       if( bp)
  800.       {
  801.          bp->remain = rem;
  802.          bp->p      = pt;
  803.       }
  804.    }
  805. #else
  806.    do
  807.    {
  808.       *p++ = c_;                             /* convert to upper & save */
  809.       i++;
  810.    }
  811.    while( tis_ident( c_ = uinput()));
  812. #endif
  813.  
  814.    *p = 0;
  815.    c = c_;
  816.    if( state == AFTERINSTR)
  817.       if( ! yytext[1] && yytext[0] == 'A')
  818.          xreturn( T_ACCU);
  819.    yy_txt2val( i);
  820.    dreturn( T_IDENT);
  821. }
  822.  
  823.  
  824. ident2_suckin( extra)
  825. char  extra;
  826. {
  827.    register byte  *p = (byte *) yytext,
  828.                   c_ = c,
  829.                   *p_table = is_what;
  830.    register int   i = 2;
  831.  
  832.    ENTER("ident2_suckin");
  833.    *p++ = extra;
  834.  
  835. #if VERSION && FINPUT_IO && QINPUT_IO && QIDENT2
  836.    {
  837.       register byte huge   *pt  = bp->p;
  838.       register byte        *tab = _uptable;
  839.       register lword       rem  = bp->remain;
  840.  
  841.       do
  842.       {
  843.          *p++ = c_;
  844.          i++;
  845.       }
  846.       while( tis_ident( c_ = quinput( rem, pt, tab)));
  847.       if( bp)
  848.       {
  849.          bp->remain = rem;
  850.          bp->p      = pt;
  851.       }
  852.    }
  853. #else
  854.    do
  855.    {
  856.       *p++ = c_;                             /* convert to upper & save */
  857.       i++;
  858.    }
  859.    while( tis_ident(c_ = uinput()));
  860. #endif
  861.    *p = 0;
  862.    c = c_;
  863.    if( state == AFTERINSTR)
  864.       if( ! yytext[1] && yytext[0] == 'A')
  865.          xreturn( T_ACCU);
  866.    yy_txt2val( i);
  867.    dreturn( T_IDENT);
  868. }
  869.  
  870.  
  871. label_suckin()
  872. {
  873.    register char  *p = yytext,
  874.                   c_ = c,
  875.                   *p_table = (char *) is_what;
  876.    register int   i = 1;
  877.  
  878.    ENTER("label_suckin");
  879.    if( c_ == '.' || tis_digit( c_))
  880.    {
  881.       c = c_;
  882.       lsyntax( E_LABELFORM);
  883.    }
  884.  
  885. #if VERSION && FINPUT_IO && QINPUT_IO && QLABEL
  886.    {
  887.       register byte huge   *pt  = bp->p;
  888.       register byte        *tab = _uptable;
  889.       register lword       rem  = bp->remain;
  890.  
  891.       while( tis_ident( c_))
  892.       {
  893.          *p++ = c_;
  894.          i++;
  895.          c_   = quinput( rem, pt, tab);
  896.       }
  897.       if( bp)
  898.       {
  899.          bp->remain = rem;
  900.          bp->p      = pt;
  901.       }
  902.    }
  903. #else
  904.    while( tis_ident(c_))                     /* Suck in macro call or   */
  905.    {                                         /* instruction             */
  906.       *p++ = c_;                             /* convert to upper & save */
  907.       i++;
  908.       c_   = uinput();                       /* get fresh input         */
  909.    }
  910. #endif
  911.  
  912.    if( p[-1] == ':' && i > 2)       /* kill trailing : for labels */
  913.    {
  914.       --i;
  915.       --p;
  916.    }
  917.    *p = 0;
  918.    c = c_;
  919.    yy_txt2val( i);
  920.    dreturn( T_LABEL);
  921. }
  922.  
  923.  
  924. void junk_suckin( error)
  925. char  *error;
  926. {
  927.    register byte  *p = (byte *) yytext;
  928.  
  929.    ENTER("junk_suckin");
  930.    while( c > ' ' && c != ';' && c != ',') /* Errors.. so we don't care */
  931.    {                                        /* about speed anyway.       */
  932.       *p++ = c;
  933.       c    = uinput();
  934.    }
  935.    *p = 0;
  936.    ALEAVE();
  937.    lsyntax( error);
  938. }
  939.  
  940.  
  941. string_suckin()
  942. {
  943.    register byte       *p = (byte *) yytext + 2;
  944.    register unsigned   i = 0;
  945.  
  946.    ENTER("string_suckin");
  947. #if VERSION && FINPUT_IO && QINPUT_IO && QSTRING
  948.    {
  949.       register byte huge   *pt = bp->p;
  950.       register lword       rem = bp->remain;
  951.  
  952.       while( (*p++ = qinput( rem, pt)) != '\"')
  953.          i++;
  954.       if( bp)
  955.       {
  956.          bp->remain = rem;
  957.          bp->p      = pt;
  958.       }
  959.    }
  960. #else
  961.    while( (*p++ = input()) != '\"')
  962.       i++;
  963. #endif
  964.    p[-1] = 0;
  965.    dbyte( yytext, wasstrlen = i);
  966.    i += 3;           /* 2 for i, 1 for strlen */
  967.    yy_txt2val( i);
  968.    fdreturn( T_STRING);
  969. }
  970.  
  971. char  *make_string( s)
  972. register char  *s;
  973. {
  974.    register char  *q;
  975.    register int   i;
  976.    char           *t;
  977.    
  978.    ENTER("make_string");
  979.    {
  980.       register char  *src = s;
  981.       for( src = s, i = 0; *src++; i++);
  982.    }
  983.    q  = t = str_alloc( i + 3);
  984.    dbyte( q, i);
  985.    q += 2;
  986.    
  987.    while( i > 4)
  988.    {
  989.       *q++ = *s++;
  990.       *q++ = *s++;
  991.       *q++ = *s++;
  992.       *q++ = *s++;
  993.       i -= 4;
  994.    }
  995.    do
  996.       *q++ = *s++;
  997.    while( --i);
  998.    
  999.    LEAVE();
  1000.    return( t);
  1001. }
  1002.  
  1003. file_suckin()
  1004. {
  1005.    register byte  *p = (byte *) yytext,
  1006.                    c_ = (c >= 'A' && c <= 'Z') ? c + 32 : c;
  1007.    register int   i  = 1;
  1008.  
  1009.    ENTER("file_suckin");
  1010.    do
  1011.    {
  1012.       *p++ = c_;
  1013.       i++;
  1014.       if ( (c_ = input()) == '/' || c_ == '>')
  1015.          c_ = '\\';
  1016.    }
  1017.    while( is_ident( c_) || c_ == '\\');
  1018.    *p = 0;
  1019.    c = c_;
  1020.    yy_txt2val( i);
  1021.    dreturn( T_FILE);
  1022. }
  1023.  
  1024. float_suckin()
  1025. {
  1026.    char     *p    = yytext;
  1027.    int      eflag = 1,
  1028.             pflag = 1,
  1029.             jflag = 0,
  1030.             kflag = 1;
  1031.  
  1032.    ENTER("float_suckin");
  1033.    while( (is_float(c) || ((c == '+' || c == '-') && (jflag || kflag)))
  1034.             && (c != '.' || (pflag && eflag))
  1035.             && (c != 'E' || eflag))
  1036.    {
  1037.       if( (c == '+') || (c == '-'))
  1038.          kflag = 0;
  1039.       if( c == '.')
  1040.          pflag = 0;
  1041.       jflag = 0;
  1042.       if( c == 'E')
  1043.       {
  1044.          pflag = eflag = 0;
  1045.          jflag = 1;
  1046.       }
  1047.       *p++ = c;
  1048.       c = uinput();
  1049.    }
  1050.    *p = 0;
  1051.    dropfloat( yytext);
  1052.    dreturn( T_XFLOAT);
  1053. }
  1054.  
  1055. /* ---------------------------------------------------------- */
  1056. /*       To make this more generic, it would be good to       */
  1057. /*       parametrize (sp?) this macro a bit more              */
  1058. /* ---------------------------------------------------------- */
  1059. #define nextdigit( _recurs)                                             \
  1060.    if( tis_digit( c_ = uinput()))                                       \
  1061.    {                                                                    \
  1062.       tmp  = val + val;                                                 \
  1063.       val  = (tmp << 2) + tmp;                                          \
  1064.       val += c_ - '0';                                                  \
  1065.       _recurs                                                           \
  1066.    }
  1067.  
  1068. #define finaldigit()                                                    \
  1069.    if( tis_digit( c_ = uinput()))                                       \
  1070.    {                                                                    \
  1071.       if( val >= 6553 && (val > 6553 || c_ >= '6')) /* This looks */    \
  1072.       {                                             /* worse than */    \
  1073.          c = c_;                                    /* it is      */    \
  1074. synerr:                                                                 \
  1075.          lsyntax( E_INTSIZE);                                           \
  1076.       }                                                                 \
  1077.       tmp  = val + val;                                                 \
  1078.       val  = (tmp << 2) + tmp;                                          \
  1079.       yylval = (lword) (val + c_ - '0');                                \
  1080.       if( tis_digit( c = uinput()))                                     \
  1081.          goto synerr;                                                   \
  1082.       IMESS("Int number is %ld", yylval, 4);                            \
  1083.       xreturn( T_NUMBER);                                               \
  1084.    }
  1085.  
  1086. /* ---------------------------------------------------------- */
  1087. /* Suck in a int value. Most probably fuinputting the number  */
  1088. /* into yytext and converting it later with nextdigit would   */
  1089. /* be faster. remains to be tested.                           */
  1090. /* ---------------------------------------------------------- */
  1091. int_suckin()
  1092. {
  1093.    register word     val = c - '0', tmp;
  1094.    register byte     c_,
  1095.                     *p_table = is_what;
  1096.  
  1097.    ENTER("int_suckin");
  1098.    nextdigit( nextdigit( nextdigit( finaldigit()))); /* can you dig it ? */
  1099.    c = c_;
  1100.    yylval = (lword) val;
  1101.    IMESS("Int number is %ld", yylval, 4);
  1102.    xreturn( T_NUMBER);
  1103. }
  1104.  
  1105. /* ---------------------------------------------------------- */
  1106. /* Suck in a hex value, we assume that, the '$' has been      */
  1107. /* removed before.                                            */
  1108. /* ---------------------------------------------------------- */
  1109. hex_suckin()
  1110. {
  1111.    register byte        *p  = (byte *) yytext,
  1112.                         c_,
  1113.                         *p_table = is_what;
  1114.    register unsigned    val = 0,
  1115.                         i   = 4;
  1116.  
  1117.    ENTER("hex_suckin");
  1118.    do
  1119.       if( tis_hex(c_ = uinput()))
  1120.       {
  1121.          *p++ = c_;
  1122.          val  <<= 4;
  1123.          val  += (c_ >= 'A')  ? c_ - 'A' + 10  : c_ - '0';
  1124.       }
  1125.       else
  1126.       {
  1127.          c = c_;
  1128.          if( i == 4)
  1129.             lsyntax("That hex number looks mighty strange");
  1130.          yylval = (lword) val;
  1131.          IMESS("calced hexnumber = %x", (lword) val, 2);
  1132.          dreturn( T_NUMBER);
  1133.       }
  1134.    while( i--);
  1135.    c = c_;
  1136.    lsyntax(E_HEXLEN);
  1137. }
  1138.  
  1139.  
  1140. #include "md_suck.c"
  1141.  
  1142. /* ---------------------------------------------------------- */
  1143. /* If a lsyntax error occurs, we'll give a nice message and   */
  1144. /* then go back to the business at hand. Tokenizing.          */
  1145. /* This is not supposed to find EOF errors, that's for the    */
  1146. /* I/O routines.                                              */
  1147. /* ---------------------------------------------------------- */
  1148. void lsyntax( err)
  1149. char  *err;
  1150. {
  1151.    if( yytext[0])
  1152.       nserror( err, yytext);
  1153.    else
  1154.       nterror( err, (int) c);
  1155.    longjmp( syn_panic, 1);
  1156. }
  1157.  
  1158. /* ---------------------------------------------------------- */
  1159. /*           Mallocer for identifier and other strings        */
  1160. /*                                                            */
  1161. /*  (Keeping the fingers crossed that this is faster than a)  */
  1162. /*                       (simple malloc)                      */
  1163. /* ---------------------------------------------------------- */
  1164. typedef struct _str_m
  1165. {
  1166.    lword                free;
  1167.    char huge            *space;
  1168.    struct _str_m huge   *before;
  1169. } str_m;
  1170.  
  1171. static str_m huge *st_h;
  1172.  
  1173. char   *str_alloc( size)
  1174. int   size;
  1175. {
  1176.    register str_m huge  *p;
  1177.    register char  huge  *q;
  1178. #if STATISTICS
  1179.    extern   word     _a_char, _m_char;
  1180.    extern  lword     _z_char, _s_char;
  1181. #endif
  1182.  
  1183.    ENTER("str_alloc");
  1184. #if STATISTICS
  1185.    _a_char++;
  1186.    _z_char += size;
  1187. #endif
  1188. #if DEBUG
  1189.    IMESS("Requested size $%lX", (lword) (size_t) size, 4);
  1190.    if( st_h)
  1191.    {
  1192.       IMESS("st_h == $%lX", (lword) st_h, 4);
  1193.       IMESS("st_h->free : $%lX", (lword) st_h->free, 4);
  1194.       IMESS("st_h->space: $%lX", (lword) st_h->space, 4);
  1195.    }
  1196. #endif
  1197.    if( (p = st_h) && p->free >= (lword) size)
  1198.    {
  1199. letsdoit:
  1200.       p->free  -= (lword) size;
  1201.       q         = p->space;
  1202.       p->space += (lword) size;
  1203.       IMESS("sending $%lX as address", (lword) q, 4);
  1204.       IMESS("st_h->space: $%lX", (lword) st_h->space, 4);
  1205.       LEAVE();
  1206.       return( q);
  1207.    }
  1208. #if STATISTICS
  1209.    _m_char++;
  1210.    _s_char = sizeof(str_m) + STRMAX;
  1211. #endif
  1212.    MESS("New big block to allocate");
  1213.    p         = (str_m huge *) nmalloc( (long) sizeof(str_m) + STRMAX);
  1214.    p->free   = (lword) STRMAX;
  1215.    p->space  = (char huge *) p + sizeof( str_m);
  1216.    p->before = st_h;
  1217.    st_h      = p;
  1218.    if( size > STRMAX)
  1219.       nierror("An unusally large string forces NASM65 to crash");
  1220.    goto letsdoit;
  1221. }
  1222.  
  1223.  
  1224. void yy_txt2val( i)
  1225. register int   i;
  1226. {
  1227.    register char  *src = yytext,
  1228.                   *q;
  1229.  
  1230. #if VERSION
  1231.    register str_m huge  *p = st_h;
  1232.  
  1233.    ENTER("yy_txt2val");
  1234.    if( p->free >= (lword) i)
  1235.    {
  1236.       p->free  -= (lword) i;
  1237.       q         = p->space;
  1238.       p->space += (lword) i;
  1239.    }
  1240.    else
  1241.       q = str_alloc( i);
  1242. #else
  1243.    ENTER("yy_txt2val");
  1244.  
  1245.    q = str_alloc( i);
  1246. #endif
  1247.    yylval = (lword) q;
  1248.  
  1249.    while( i > 4)
  1250.    {
  1251.       *q++ = *src++;
  1252.       *q++ = *src++;
  1253.       *q++ = *src++;
  1254.       *q++ = *src++;
  1255.       i -= 4;
  1256.    }
  1257.    do
  1258.       *q++ = *src++;
  1259.    while( --i);
  1260.    IMESS("st_h->space: $%lX", (lword) st_h->space, 4);
  1261.    LEAVE();
  1262. }
  1263.  
  1264. /* ------------------------------------------------------------
  1265.    Words to keep in mind:
  1266.  
  1267.                         "Little green man
  1268.                            about four foot
  1269.                          maybe he want
  1270.                            to kick some butt!"   (Vai)
  1271.  
  1272.    ------------------------------------------------------------ */
  1273.