[BACK]Return to fgen.l CVS log [TXT][DIR] Up to [local] / src / usr.bin / fgen

Annotation of src/usr.bin/fgen/fgen.l, Revision 1.15

1.1       jason       1: %{
1.15    ! jmc         2: /*     $OpenBSD: fgen.l,v 1.14 2021/12/13 18:28:40 deraadt Exp $       */
1.13      otto        3: /*     $NetBSD: fgen.l,v 1.37 2016/03/08 20:13:44 christos Exp $       */
1.1       jason       4: /* FLEX input for FORTH input file scanner */
                      5: /*
                      6:  * Copyright (c) 1998 Eduardo Horvath.
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     19:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     20:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     21:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     22:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     23:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     24:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     25:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     26:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     27:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     28:  */
                     29: /*
                     30:        Specifications are as follows:
                     31:
                     32:        The function "yylex()" always returns a pointer to a structure:
                     33:
                     34:            struct tok {
                     35:                int type;
                     36:                char *text;
                     37:            }
                     38:            #define TOKEN struct tok
                     39: */
1.13      otto       40:
1.1       jason      41: %}
                     42:
                     43: %option yylineno
                     44:
                     45: hex    [0-9A-Fa-f]
1.13      otto       46: hexdot [0-9A-Fa-f.]
1.1       jason      47: white  [ \t\n\r\f]
                     48: tail   {white}
                     49:
                     50: %{
                     51: #include <sys/types.h>
1.13      otto       52: #include <arpa/inet.h>
1.1       jason      53:
                     54: #include <assert.h>
                     55: #include <err.h>
                     56: #include <errno.h>
                     57: #include <fcntl.h>
                     58: #include <stdarg.h>
                     59: #include <stdio.h>
                     60: #include <string.h>
                     61: #include <unistd.h>
1.13      otto       62: #include <util.h>
1.1       jason      63:
                     64: #include "fgen.h"
1.13      otto       65: static TOKEN ltoken;
1.1       jason      66:
                     67: /*
                     68:  * Global variables that control the parse state.
                     69:  */
                     70:
1.13      otto       71: static struct fcode *dictionary = NULL;
                     72: static struct macro *aliases = NULL;
                     73: static int outf = 1; /* stdout */
                     74: static int state = 0;
                     75: static int nextfcode = 0x800;
                     76: static int numbase = TOK_HEX;
                     77: static long outpos;
                     78: static char *outbuf = NULL;
                     79: static char *outfile, *infile;
1.1       jason      80: #define BUFCLICK       (1024*1024)
1.13      otto       81: static size_t outbufsiz = 0;
                     82: static char *myname = NULL;
                     83: static int offsetsize = 8;
                     84: static int defining = 0;
                     85: static int tokenizer = 0;
                     86: static int need_end0 = 1;
1.1       jason      87:
                     88: #define PSTKSIZ                1024
1.13      otto       89: static Cell parse_stack[PSTKSIZ];
                     90: static int parse_stack_ptr = 0;
1.1       jason      91:
1.13      otto       92: static void    token_err(int, const char *, const char *, const char *, ...)
                     93:     __attribute__((__format__ (printf, 4, 5))) __dead;
                     94: static YY_DECL;
1.1       jason      95:
1.13      otto       96: static int debug = 0;
1.1       jason      97: #define ASSERT if (debug) assert
1.13      otto       98: #define STATE(y, x)    do { if (debug) printf("%lx State %s: token `%s'\n", outpos, x, y); } while (0)
                     99: static int mark_fload = 0;
                    100:
                    101: void *
                    102: emalloc(size_t sz)
                    103: {
                    104:        void *p = malloc(sz);
                    105:        if (p == NULL)
                    106:                err(1, NULL);
                    107:        return p;
                    108: }
                    109:
                    110: char *
                    111: estrdup(const char *s)
                    112: {
                    113:        char *p = strdup(s);
                    114:        if (p == NULL)
                    115:                err(1, NULL);
                    116:        return p;
                    117: }
                    118:
                    119: void *
                    120: erealloc(void *p, size_t sz)
                    121: {
                    122:        void *q = realloc(p, sz);
                    123:        if (q == NULL)
                    124:                err(1, NULL);
                    125:        return q;
                    126: }
1.1       jason     127:
                    128: %}
                    129:
1.13      otto      130: %option nounput
                    131:
1.1       jason     132: %%
                    133:
1.13      otto      134: 0              { ltoken.type = TOK_OTHER; ltoken.text = yytext; return &ltoken; }
                    135:
                    136: 1              { ltoken.type = TOK_OTHER; ltoken.text = yytext; return &ltoken; }
1.1       jason     137:
1.13      otto      138: 2              { ltoken.type = TOK_OTHER; ltoken.text = yytext; return &ltoken; }
1.1       jason     139:
1.13      otto      140: 3              { ltoken.type = TOK_OTHER; ltoken.text = yytext; return &ltoken; }
1.1       jason     141:
1.13      otto      142: -1             { ltoken.type = TOK_OTHER; ltoken.text = yytext; return &ltoken; }
1.1       jason     143:
1.13      otto      144: \.             { ltoken.type = TOK_OTHER; ltoken.text = yytext; return &ltoken; }
1.1       jason     145:
                    146: {white}*               /* whitespace -- keep looping */ ;
                    147:
                    148: \\[^\n]*\n             /* end of line comment -- keep looping */ { STATE(yytext, "EOL comment"); }
                    149:
1.13      otto      150: -?{hex}{hexdot}*       { ltoken.type = TOK_NUMBER; ltoken.text = yytext;
                    151:                                        return &ltoken; }
                    152:
                    153: \'.\'          { ltoken.type = TOK_C_LIT; ltoken.text = yytext; return &ltoken; }
1.1       jason     154:
1.13      otto      155: \"{white}*(\\\"|[^"])*\"       { ltoken.type = TOK_STRING_LIT; ltoken.text = yytext;
                    156:                                return &ltoken; } /* String started by `"' or `."' */
1.1       jason     157:
1.13      otto      158: \.\({white}*(\\\"|[^)])*\)     { ltoken.type = TOK_PSTRING; ltoken.text = yytext;
                    159:                                return &ltoken; } /* String of type `.(.....)' */
1.1       jason     160:
1.13      otto      161: \.\"{white}*(\\\"|[^"])*\"     { ltoken.type = TOK_PSTRING; ltoken.text = yytext;
                    162:                                return &ltoken; }
1.1       jason     163:
1.13      otto      164: [aA][bB][oO][rR][tT]\"{white}*(\\\"|[^"])*\" { ltoken.type = TOK_ABORT_S;
                    165:                                ltoken.text = yytext;  return &ltoken; }
1.1       jason     166:
1.13      otto      167: "("            { ltoken.type = TOK_COMMENT; ltoken.text = yytext;
                    168:                                return &ltoken; }
1.1       jason     169:
1.13      otto      170: ":"            { ltoken.type = TOK_COLON; ltoken.text = yytext;
                    171:                                return &ltoken; }
1.1       jason     172:
1.13      otto      173: ";"            { ltoken.type = TOK_SEMICOLON; ltoken.text = yytext;
                    174:                                return &ltoken; }
1.1       jason     175:
1.13      otto      176: \'             { ltoken.type = TOK_TOKENIZE; ltoken.text = yytext;
                    177:                                return &ltoken; }
1.1       jason     178:
1.13      otto      179: [aA][gG][aA][iI][nN]   { ltoken.type = TOK_AGAIN; ltoken.text = yytext;
                    180:                                return &ltoken; }
1.1       jason     181:
1.13      otto      182: [aA][lL][iI][aA][sS]   { ltoken.type = TOK_ALIAS; ltoken.text = yytext;
                    183:                                return &ltoken; }
1.1       jason     184:
1.13      otto      185: \[\'\]                 { ltoken.type = TOK_GETTOKEN; ltoken.text = yytext;
                    186:                                return &ltoken; }
1.1       jason     187:
1.13      otto      188: [aA][sS][cC][iI][iI]   { ltoken.type = TOK_ASCII; ltoken.text = yytext;
                    189:                                return &ltoken; }
1.1       jason     190:
1.13      otto      191: [bB][eE][gG][iI][nN]   { ltoken.type = TOK_BEGIN; ltoken.text = yytext;
                    192:                                return &ltoken; }
1.1       jason     193:
1.13      otto      194: [bB][uU][fF][fF][eE][rR]:      { ltoken.type = TOK_BUFFER; ltoken.text = yytext;
                    195:                                return &ltoken; }
1.1       jason     196:
1.13      otto      197: [cC][aA][sS][eE]       { ltoken.type = TOK_CASE; ltoken.text = yytext;
                    198:                                return &ltoken; }
1.1       jason     199:
1.13      otto      200: [cC][oO][nN][sS][tT][aA][nN][tT]       { ltoken.type = TOK_CONSTANT; ltoken.text = yytext;
                    201:                                return &ltoken; }
1.1       jason     202:
1.13      otto      203: [cC][oO][nN][tT][rR][oO][lL]   { ltoken.type = TOK_CONTROL; ltoken.text = yytext;
                    204:                                return &ltoken; }
1.1       jason     205:
1.13      otto      206: [cC][rR][eE][aA][tT][eE]       { ltoken.type = TOK_CREATE; ltoken.text = yytext;
                    207:                                return &ltoken; }
1.1       jason     208:
1.13      otto      209: [dD]#          { ltoken.type = TOK_DECIMAL; ltoken.text = yytext;
                    210:                                return &ltoken; }
1.1       jason     211:
1.13      otto      212: [dD][eE][cC][iI][mM][aA][lL]   { ltoken.type = TOK_DECIMAL; ltoken.text = yytext;
                    213:                                return &ltoken; }
1.1       jason     214:
1.13      otto      215: [dD][eE][fF][eE][rR]   { ltoken.type = TOK_DEFER; ltoken.text = yytext;
                    216:                                return &ltoken; }
1.1       jason     217:
1.13      otto      218: \??[dD][oO]    { ltoken.type = TOK_DO; ltoken.text = yytext;
                    219:                                return &ltoken; }
1.1       jason     220:
1.13      otto      221: [eE][lL][sS][eE]       { ltoken.type = TOK_ELSE; ltoken.text = yytext;
                    222:                                return &ltoken; }
1.1       jason     223:
1.13      otto      224: [eE][nN][dD]0  { ltoken.type = TOK_END0; ltoken.text = yytext;
                    225:                                return &ltoken; }
1.1       jason     226:
1.13      otto      227: [eE][nN][dD][cC][aA][sS][eE]   { ltoken.type = TOK_ENDCASE; ltoken.text = yytext;
                    228:                                return &ltoken; }
1.1       jason     229:
1.13      otto      230: [eE][nN][dD][oO][fF]   { ltoken.type = TOK_ENDOF; ltoken.text = yytext;
                    231:                                return &ltoken; }
1.1       jason     232:
1.13      otto      233: [eE][xX][tT][eE][rR][nN][aA][lL]       { ltoken.type = TOK_EXTERNAL; ltoken.text = yytext;
                    234:                                return &ltoken; }
1.1       jason     235:
1.13      otto      236: [fF][cC][oO][dD][eE]-[vV][eE][rR][sS][iI][oO][nN]2     {
                    237:                        ltoken.type = TOK_FCODE_VERSION2; ltoken.text = yytext;
                    238:                                return &ltoken; }
1.1       jason     239:
1.13      otto      240: [fF][cC][oO][dD][eE]-[eE][nN][dD]      { ltoken.type = TOK_FCODE_END; ltoken.text = yytext;
                    241:                                return &ltoken; }
1.1       jason     242:
1.13      otto      243: [fF][iI][eE][lL][dD]   { ltoken.type = TOK_FIELD; ltoken.text = yytext;
                    244:                                return &ltoken; }
1.1       jason     245:
1.13      otto      246: [hH]#          { ltoken.type = TOK_HEX; ltoken.text = yytext;
                    247:                                return &ltoken; }
1.1       jason     248:
1.13      otto      249: [hH][eE][aA][dD][eE][rR][lL][eE][sS][sS]       { ltoken.type = TOK_HEADERLESS; ltoken.text = yytext;
                    250:                                return &ltoken; }
1.1       jason     251:
1.13      otto      252: [hH][eE][aA][dD][eE][rR][sS]   { ltoken.type = TOK_HEADERS; ltoken.text = yytext;
                    253:                                return &ltoken; }
1.1       jason     254:
1.13      otto      255: [hH][eE][xX]   { ltoken.type = TOK_HEX; ltoken.text = yytext;
                    256:                                return &ltoken; }
1.1       jason     257:
1.13      otto      258: [iI][fF]               { ltoken.type = TOK_IF; ltoken.text = yytext;
                    259:                                return &ltoken; }
1.1       jason     260:
1.13      otto      261: \??[lL][eE][aA][vV][eE]        { ltoken.type = TOK_LEAVE; ltoken.text = yytext;
                    262:                                return &ltoken; }
1.1       jason     263:
1.13      otto      264: \+?[lL][oO][oO][pP]    { ltoken.type = TOK_LOOP; ltoken.text = yytext;
                    265:                                return &ltoken; }
1.1       jason     266:
1.13      otto      267: [oO]#          { ltoken.type = TOK_OCTAL; ltoken.text = yytext;
                    268:                                return &ltoken; }
1.1       jason     269:
1.13      otto      270: [oO][cC][tT][aA][lL]   { ltoken.type = TOK_OCTAL; ltoken.text = yytext;
                    271:                                return &ltoken; }
1.1       jason     272:
1.13      otto      273: [oO][fF]               { ltoken.type = TOK_OF; ltoken.text = yytext;
                    274:                                return &ltoken; }
1.1       jason     275:
1.13      otto      276: [oO][fF][fF][sS][eE][tT]16     { ltoken.type = TOK_OFFSET16; ltoken.text = yytext;
                    277:                                return &ltoken; }
1.1       jason     278:
1.13      otto      279: [rR][eE][pP][eE][aA][tT]       { ltoken.type = TOK_REPEAT; ltoken.text = yytext;
                    280:                                return &ltoken; }
1.1       jason     281:
1.13      otto      282: [sS][tT][aA][rR][tT][0124]     { ltoken.type = TOK_STARTX; ltoken.text = yytext;
                    283:                                return &ltoken; }
                    284:
                    285: [tT][hH][eE][nN]       { ltoken.type = TOK_THEN; ltoken.text = yytext;
                    286:                                return &ltoken; }
1.1       jason     287:
1.13      otto      288: [tT][oO]               { ltoken.type = TOK_TO; ltoken.text = yytext;
                    289:                                return &ltoken; }
1.1       jason     290:
1.13      otto      291: [uU][nN][tT][iI][lL]   { ltoken.type = TOK_UNTIL; ltoken.text = yytext;
                    292:                                return &ltoken; }
1.1       jason     293:
1.13      otto      294: [vV][aA][lL][uU][eE]   { ltoken.type = TOK_VALUE; ltoken.text = yytext;
                    295:                                return &ltoken; }
1.1       jason     296:
1.13      otto      297: [vV][aA][rR][iI][aA][bB][lL][eE]       { ltoken.type = TOK_VARIABLE; ltoken.text = yytext;
                    298:                                return &ltoken; }
1.1       jason     299:
1.13      otto      300: [vV][eE][rR][sS][iI][oO][nN]1  { ltoken.type = TOK_VERSION1; ltoken.text = yytext;
                    301:                                return &ltoken; }
1.1       jason     302:
1.13      otto      303: [wW][hH][iI][lL][eE]   { ltoken.type = TOK_WHILE; ltoken.text = yytext;
                    304:                                return &ltoken; }
1.1       jason     305:
1.13      otto      306: tokenizer\[    { ltoken.type = TOK_BEGTOK; ltoken.text = yytext;
                    307:                                return &ltoken; }
1.1       jason     308:
1.13      otto      309: emit-byte              { ltoken.type = TOK_EMIT_BYTE; ltoken.text = yytext;
                    310:                                return &ltoken; }
1.1       jason     311:
1.13      otto      312: \]tokenizer    { ltoken.type = TOK_ENDTOK; ltoken.text = yytext;
                    313:                                return &ltoken; }
                    314:
                    315: [fF][lL][oO][aA][dD]   { ltoken.type = TOK_FLOAD; ltoken.text = yytext;
                    316:                                return &ltoken; }
                    317:
                    318:
                    319: [^ \n\t\r\f]+  { ltoken.type = TOK_OTHER; ltoken.text = yytext;
                    320:                                return &ltoken; }
1.1       jason     321:
                    322: <<EOF>>                        { return NULL; }
                    323: %%
                    324:
                    325: /* Function definitions */
1.13      otto      326: static void push(Cell);
                    327: static Cell pop(void);
                    328: static int depth(void);
                    329: static int fadd(struct fcode *, struct fcode *);
                    330: static struct fcode *flookup(struct fcode *, const char *);
                    331: static int aadd(struct macro *, struct macro *);
                    332: static struct macro *alookup(struct macro *, const char *);
                    333: static void initdic(void);
                    334: __dead static void usage(void);
                    335: static void tokenize(YY_BUFFER_STATE);
                    336: static int emit(const char *);
                    337: static int spit(long);
                    338: static int offspit(long);
                    339: static void sspit(const char *);
                    340: static int apply_macros(YY_BUFFER_STATE, const char *);
                    341: static Cell cvt(const char *, char **, int base);
1.1       jason     342:
                    343: /*
                    344:  * Standard FCode names and numbers.  Includes standard
                    345:  * tokenizer aliases.
                    346:  */
1.13      otto      347: static struct fcode fcodes[] = {
                    348:                { "end0",                       0x0000, 0, NULL, NULL },
                    349:                { "b(lit)",                     0x0010, 0, NULL, NULL },
                    350:                { "b(')",                       0x0011, 0, NULL, NULL },
                    351:                { "b(\")",                      0x0012, 0, NULL, NULL },
                    352:                { "bbranch",                    0x0013, 0, NULL, NULL },
                    353:                { "b?branch",                   0x0014, 0, NULL, NULL },
                    354:                { "b(loop)",                    0x0015, 0, NULL, NULL },
                    355:                { "b(+loop)",                   0x0016, 0, NULL, NULL },
                    356:                { "b(do)",                      0x0017, 0, NULL, NULL },
                    357:                { "b(?do)",                     0x0018, 0, NULL, NULL },
                    358:                { "i",                          0x0019, 0, NULL, NULL },
                    359:                { "j",                          0x001a, 0, NULL, NULL },
                    360:                { "b(leave)",                   0x001b, 0, NULL, NULL },
                    361:                { "b(of)",                      0x001c, 0, NULL, NULL },
                    362:                { "execute",                    0x001d, 0, NULL, NULL },
                    363:                { "+",                          0x001e, 0, NULL, NULL },
                    364:                { "-",                          0x001f, 0, NULL, NULL },
                    365:                { "*",                          0x0020, 0, NULL, NULL },
                    366:                { "/",                          0x0021, 0, NULL, NULL },
                    367:                { "mod",                        0x0022, 0, NULL, NULL },
                    368:                { "and",                        0x0023, 0, NULL, NULL },
                    369:                { "or",                         0x0024, 0, NULL, NULL },
                    370:                { "xor",                        0x0025, 0, NULL, NULL },
                    371:                { "invert",                     0x0026, 0, NULL, NULL },
                    372:                { "lshift",                     0x0027, 0, NULL, NULL },
                    373:                { "rshift",                     0x0028, 0, NULL, NULL },
                    374:                { ">>a",                        0x0029, 0, NULL, NULL },
                    375:                { "/mod",                       0x002a, 0, NULL, NULL },
                    376:                { "u/mod",                      0x002b, 0, NULL, NULL },
                    377:                { "negate",                     0x002c, 0, NULL, NULL },
                    378:                { "abs",                        0x002d, 0, NULL, NULL },
                    379:                { "min",                        0x002e, 0, NULL, NULL },
                    380:                { "max",                        0x002f, 0, NULL, NULL },
                    381:                { ">r",                         0x0030, 0, NULL, NULL },
                    382:                { "r>",                         0x0031, 0, NULL, NULL },
                    383:                { "r@",                         0x0032, 0, NULL, NULL },
                    384:                { "exit",                       0x0033, 0, NULL, NULL },
                    385:                { "0=",                         0x0034, 0, NULL, NULL },
                    386:                { "0<>",                        0x0035, 0, NULL, NULL },
                    387:                { "0<",                         0x0036, 0, NULL, NULL },
                    388:                { "0<=",                        0x0037, 0, NULL, NULL },
                    389:                { "0>",                         0x0038, 0, NULL, NULL },
                    390:                { "0>=",                        0x0039, 0, NULL, NULL },
                    391:                { "<",                          0x003a, 0, NULL, NULL },
                    392:                { ">",                          0x003b, 0, NULL, NULL },
                    393:                { "=",                          0x003c, 0, NULL, NULL },
                    394:                { "<>",                         0x003d, 0, NULL, NULL },
                    395:                { "u>",                         0x003e, 0, NULL, NULL },
                    396:                { "u<=",                        0x003f, 0, NULL, NULL },
                    397:                { "u<",                         0x0040, 0, NULL, NULL },
                    398:                { "u>=",                        0x0041, 0, NULL, NULL },
                    399:                { ">=",                         0x0042, 0, NULL, NULL },
                    400:                { "<=",                         0x0043, 0, NULL, NULL },
                    401:                { "between",                    0x0044, 0, NULL, NULL },
                    402:                { "within",                     0x0045, 0, NULL, NULL },
                    403:                { "drop",                       0x0046, 0, NULL, NULL },
                    404:                { "dup",                        0x0047, 0, NULL, NULL },
                    405:                { "over",                       0x0048, 0, NULL, NULL },
                    406:                { "swap",                       0x0049, 0, NULL, NULL },
                    407:                { "rot",                        0x004a, 0, NULL, NULL },
                    408:                { "-rot",                       0x004b, 0, NULL, NULL },
                    409:                { "tuck",                       0x004c, 0, NULL, NULL },
                    410:                { "nip",                        0x004d, 0, NULL, NULL },
                    411:                { "pick",                       0x004e, 0, NULL, NULL },
                    412:                { "roll",                       0x004f, 0, NULL, NULL },
                    413:                { "?dup",                       0x0050, 0, NULL, NULL },
                    414:                { "depth",                      0x0051, 0, NULL, NULL },
                    415:                { "2drop",                      0x0052, 0, NULL, NULL },
                    416:                { "2dup",                       0x0053, 0, NULL, NULL },
                    417:                { "2over",                      0x0054, 0, NULL, NULL },
                    418:                { "2swap",                      0x0055, 0, NULL, NULL },
                    419:                { "2rot",                       0x0056, 0, NULL, NULL },
                    420:                { "2/",                         0x0057, 0, NULL, NULL },
                    421:                { "u2/",                        0x0058, 0, NULL, NULL },
                    422:                { "2*",                         0x0059, 0, NULL, NULL },
                    423:                { "/c",                         0x005a, 0, NULL, NULL },
                    424:                { "/w",                         0x005b, 0, NULL, NULL },
                    425:                { "/l",                         0x005c, 0, NULL, NULL },
                    426:                { "/n",                         0x005d, 0, NULL, NULL },
                    427:                { "ca+",                        0x005e, 0, NULL, NULL },
                    428:                { "wa+",                        0x005f, 0, NULL, NULL },
                    429:                { "la+",                        0x0060, 0, NULL, NULL },
                    430:                { "na+",                        0x0061, 0, NULL, NULL },
                    431:                { "char+",                      0x0062, 0, NULL, NULL },
                    432:                { "wa1+",                       0x0063, 0, NULL, NULL },
                    433:                { "la1+",                       0x0064, 0, NULL, NULL },
                    434:                { "cell+",                      0x0065, 0, NULL, NULL },
                    435:                { "chars",                      0x0066, 0, NULL, NULL },
                    436:                { "/w*",                        0x0067, 0, NULL, NULL },
                    437:                { "/l*",                        0x0068, 0, NULL, NULL },
                    438:                { "cells",                      0x0069, 0, NULL, NULL },
                    439:                { "on",                         0x006a, 0, NULL, NULL },
                    440:                { "off",                        0x006b, 0, NULL, NULL },
                    441:                { "+!",                         0x006c, 0, NULL, NULL },
                    442:                { "@",                          0x006d, 0, NULL, NULL },
                    443:                { "l@",                         0x006e, 0, NULL, NULL },
                    444:                { "w@",                         0x006f, 0, NULL, NULL },
                    445:                { "<w@",                        0x0070, 0, NULL, NULL },
                    446:                { "c@",                         0x0071, 0, NULL, NULL },
                    447:                { "!",                          0x0072, 0, NULL, NULL },
                    448:                { "l!",                         0x0073, 0, NULL, NULL },
                    449:                { "w!",                         0x0074, 0, NULL, NULL },
                    450:                { "c!",                         0x0075, 0, NULL, NULL },
                    451:                { "2@",                         0x0076, 0, NULL, NULL },
                    452:                { "2!",                         0x0077, 0, NULL, NULL },
                    453:                { "move",                       0x0078, 0, NULL, NULL },
                    454:                { "fill",                       0x0079, 0, NULL, NULL },
                    455:                { "comp",                       0x007a, 0, NULL, NULL },
                    456:                { "noop",                       0x007b, 0, NULL, NULL },
                    457:                { "lwsplit",                    0x007c, 0, NULL, NULL },
                    458:                { "wjoin",                      0x007d, 0, NULL, NULL },
                    459:                { "lbsplit",                    0x007e, 0, NULL, NULL },
                    460:                { "bljoin",                     0x007f, 0, NULL, NULL },
                    461:                { "wbflip",                     0x0080, 0, NULL, NULL },
                    462:                { "upc",                        0x0081, 0, NULL, NULL },
                    463:                { "lcc",                        0x0082, 0, NULL, NULL },
                    464:                { "pack",                       0x0083, 0, NULL, NULL },
                    465:                { "count",                      0x0084, 0, NULL, NULL },
                    466:                { "body>",                      0x0085, 0, NULL, NULL },
                    467:                { ">body",                      0x0086, 0, NULL, NULL },
                    468:                { "fcode-revision",             0x0087, 0, NULL, NULL },
                    469:                { "span",                       0x0088, 0, NULL, NULL },
                    470:                { "unloop",                     0x0089, 0, NULL, NULL },
                    471:                { "expect",                     0x008a, 0, NULL, NULL },
                    472:                { "alloc-mem",                  0x008b, 0, NULL, NULL },
                    473:                { "free-mem",                   0x008c, 0, NULL, NULL },
                    474:                { "key?",                       0x008d, 0, NULL, NULL },
                    475:                { "key",                        0x008e, 0, NULL, NULL },
                    476:                { "emit",                       0x008f, 0, NULL, NULL },
                    477:                { "type",                       0x0090, 0, NULL, NULL },
                    478:                { "(cr",                        0x0091, 0, NULL, NULL },
                    479:                { "cr",                         0x0092, 0, NULL, NULL },
                    480:                { "#out",                       0x0093, 0, NULL, NULL },
                    481:                { "#line",                      0x0094, 0, NULL, NULL },
                    482:                { "hold",                       0x0095, 0, NULL, NULL },
                    483:                { "<#",                         0x0096, 0, NULL, NULL },
                    484:                { "u#>",                        0x0097, 0, NULL, NULL },
                    485:                { "sign",                       0x0098, 0, NULL, NULL },
                    486:                { "u#",                         0x0099, 0, NULL, NULL },
                    487:                { "u#s",                        0x009a, 0, NULL, NULL },
                    488:                { "u.",                         0x009b, 0, NULL, NULL },
                    489:                { "u.r",                        0x009c, 0, NULL, NULL },
                    490:                { ".",                          0x009d, 0, NULL, NULL },
                    491:                { ".r",                         0x009e, 0, NULL, NULL },
                    492:                { ".s",                         0x009f, 0, NULL, NULL },
                    493:                { "base",                       0x00a0, 0, NULL, NULL },
                    494:                { "convert",                    0x00a1, 0, NULL, NULL },
                    495:                { "$number",                    0x00a2, 0, NULL, NULL },
                    496:                { "digit",                      0x00a3, 0, NULL, NULL },
                    497:                { "-1",                         0x00a4, 0, NULL, NULL },
                    498:                { "true",                       0x00a4, 0, NULL, NULL },
                    499:                { "0",                          0x00a5, 0, NULL, NULL },
                    500:                { "1",                          0x00a6, 0, NULL, NULL },
                    501:                { "2",                          0x00a7, 0, NULL, NULL },
                    502:                { "3",                          0x00a8, 0, NULL, NULL },
                    503:                { "bl",                         0x00a9, 0, NULL, NULL },
                    504:                { "bs",                         0x00aa, 0, NULL, NULL },
                    505:                { "bell",                       0x00ab, 0, NULL, NULL },
                    506:                { "bounds",                     0x00ac, 0, NULL, NULL },
                    507:                { "here",                       0x00ad, 0, NULL, NULL },
                    508:                { "aligned",                    0x00ae, 0, NULL, NULL },
                    509:                { "wbsplit",                    0x00af, 0, NULL, NULL },
                    510:                { "bwjoin",                     0x00b0, 0, NULL, NULL },
                    511:                { "b(<mark)",                   0x00b1, 0, NULL, NULL },
                    512:                { "b(>resolve)",                0x00b2, 0, NULL, NULL },
                    513:                { "set-token-table",            0x00b3, 0, NULL, NULL },
                    514:                { "set-table",                  0x00b4, 0, NULL, NULL },
                    515:                { "new-token",                  0x00b5, 0, NULL, NULL },
                    516:                { "named-token",                0x00b6, 0, NULL, NULL },
                    517:                { "b(:)",                       0x00b7, 0, NULL, NULL },
                    518:                { "b(value)",                   0x00b8, 0, NULL, NULL },
                    519:                { "b(variable)",                0x00b9, 0, NULL, NULL },
                    520:                { "b(constant)",                0x00ba, 0, NULL, NULL },
                    521:                { "b(create)",                  0x00bb, 0, NULL, NULL },
                    522:                { "b(defer)",                   0x00bc, 0, NULL, NULL },
                    523:                { "b(buffer:)",                 0x00bd, 0, NULL, NULL },
                    524:                { "b(field)",                   0x00be, 0, NULL, NULL },
                    525:                { "b(code)",                    0x00bf, 0, NULL, NULL },
                    526:                { "instance",                   0x00c0, 0, NULL, NULL },
                    527:                { "b(;)",                       0x00c2, 0, NULL, NULL },
                    528:                { "b(to)",                      0x00c3, 0, NULL, NULL },
                    529:                { "b(case)",                    0x00c4, 0, NULL, NULL },
                    530:                { "b(endcase)",                 0x00c5, 0, NULL, NULL },
                    531:                { "b(endof)",                   0x00c6, 0, NULL, NULL },
                    532:                { "#",                          0x00c7, 0, NULL, NULL },
                    533:                { "#s",                         0x00c8, 0, NULL, NULL },
                    534:                { "#>",                         0x00c9, 0, NULL, NULL },
                    535:                { "external-token",             0x00ca, 0, NULL, NULL },
                    536:                { "$find",                      0x00cb, 0, NULL, NULL },
                    537:                { "offset16",                   0x00cc, 0, NULL, NULL },
                    538:                { "evaluate",                   0x00cd, 0, NULL, NULL },
                    539:                { "c,",                         0x00d0, 0, NULL, NULL },
                    540:                { "w,",                         0x00d1, 0, NULL, NULL },
                    541:                { "l,",                         0x00d2, 0, NULL, NULL },
                    542:                { ",",                          0x00d3, 0, NULL, NULL },
                    543:                { "um*",                        0x00d4, 0, NULL, NULL },
                    544:                { "um/mod",                     0x00d5, 0, NULL, NULL },
                    545:                { "d+",                         0x00d8, 0, NULL, NULL },
                    546:                { "d-",                         0x00d9, 0, NULL, NULL },
                    547:                { "get-token",                  0x00da, 0, NULL, NULL },
                    548:                { "set-token",                  0x00db, 0, NULL, NULL },
                    549:                { "state",                      0x00dc, 0, NULL, NULL },
                    550:                { "compile,",                   0x00dd, 0, NULL, NULL },
                    551:                { "behavior",                   0x00de, 0, NULL, NULL },
                    552:                { "start0",                     0x00f0, 0, NULL, NULL },
                    553:                { "start1",                     0x00f1, 0, NULL, NULL },
                    554:                { "start2",                     0x00f2, 0, NULL, NULL },
                    555:                { "start4",                     0x00f3, 0, NULL, NULL },
                    556:                { "ferror",                     0x00fc, 0, NULL, NULL },
                    557:                { "version1",                   0x00fd, 0, NULL, NULL },
                    558:                { "4-byte-id",                  0x00fe, 0, NULL, NULL },
                    559:                { "end1",                       0x00ff, 0, NULL, NULL },
                    560:                { "dma-alloc",                  0x0101, 0, NULL, NULL },
                    561:                { "my-address",                 0x0102, 0, NULL, NULL },
                    562:                { "my-space",                   0x0103, 0, NULL, NULL },
                    563:                { "memmap",                     0x0104, 0, NULL, NULL },
                    564:                { "free-virtual",               0x0105, 0, NULL, NULL },
                    565:                { ">physical",                  0x0106, 0, NULL, NULL },
                    566:                { "my-params",                  0x010f, 0, NULL, NULL },
                    567:                { "property",                   0x0110, 0, NULL, NULL },
                    568:                { "encode-int",                 0x0111, 0, NULL, NULL },
                    569:                { "encode+",                    0x0112, 0, NULL, NULL },
                    570:                { "encode-phys",                0x0113, 0, NULL, NULL },
                    571:                { "encode-string",              0x0114, 0, NULL, NULL },
                    572:                { "encode-bytes",               0x0115, 0, NULL, NULL },
                    573:                { "reg",                        0x0116, 0, NULL, NULL },
                    574:                { "intr",                       0x0117, 0, NULL, NULL },
                    575:                { "driver",                     0x0118, 0, NULL, NULL },
                    576:                { "model",                      0x0119, 0, NULL, NULL },
                    577:                { "device-type",                0x011a, 0, NULL, NULL },
                    578:                { "parse-2int",                 0x011b, 0, NULL, NULL },
                    579:                { "is-install",                 0x011c, 0, NULL, NULL },
                    580:                { "is-remove",                  0x011d, 0, NULL, NULL },
                    581:                { "is-selftest",                0x011e, 0, NULL, NULL },
                    582:                { "new-device",                 0x011f, 0, NULL, NULL },
                    583:                { "diagnostic-mode?",           0x0120, 0, NULL, NULL },
                    584:                { "display-status",             0x0121, 0, NULL, NULL },
                    585:                { "memory-test-suite",          0x0122, 0, NULL, NULL },
                    586:                { "group-code",                 0x0123, 0, NULL, NULL },
                    587:                { "mask",                       0x0124, 0, NULL, NULL },
                    588:                { "get-msecs",                  0x0125, 0, NULL, NULL },
                    589:                { "ms",                         0x0126, 0, NULL, NULL },
                    590:                { "finish-device",              0x0127, 0, NULL, NULL },
                    591:                { "decode-phys",                0x0128, 0, NULL, NULL },
                    592:                { "map-low",                    0x0130, 0, NULL, NULL },
                    593:                { "sbus-intr>cpu",              0x0131, 0, NULL, NULL },
                    594:                { "#lines",                     0x0150, 0, NULL, NULL },
                    595:                { "#columns",                   0x0151, 0, NULL, NULL },
                    596:                { "line#",                      0x0152, 0, NULL, NULL },
                    597:                { "column#",                    0x0153, 0, NULL, NULL },
                    598:                { "inverse?",                   0x0154, 0, NULL, NULL },
                    599:                { "inverse-screen?",            0x0155, 0, NULL, NULL },
                    600:                { "frame-buffer-busy?",         0x0156, 0, NULL, NULL },
                    601:                { "draw-character",             0x0157, 0, NULL, NULL },
                    602:                { "reset-screen",               0x0158, 0, NULL, NULL },
                    603:                { "toggle-cursor",              0x0159, 0, NULL, NULL },
                    604:                { "erase-screen",               0x015a, 0, NULL, NULL },
                    605:                { "blink-screen",               0x015b, 0, NULL, NULL },
                    606:                { "invert-screen",              0x015c, 0, NULL, NULL },
                    607:                { "insert-characters",          0x015d, 0, NULL, NULL },
                    608:                { "delete-characters",          0x015e, 0, NULL, NULL },
                    609:                { "insert-lines",               0x015f, 0, NULL, NULL },
                    610:                { "delete-lines",               0x0160, 0, NULL, NULL },
                    611:                { "draw-logo",                  0x0161, 0, NULL, NULL },
                    612:                { "frame-buffer-addr",          0x0162, 0, NULL, NULL },
                    613:                { "screen-height",              0x0163, 0, NULL, NULL },
                    614:                { "screen-width",               0x0164, 0, NULL, NULL },
                    615:                { "window-top",                 0x0165, 0, NULL, NULL },
                    616:                { "window-left",                0x0166, 0, NULL, NULL },
                    617:                { "default-font",               0x016a, 0, NULL, NULL },
                    618:                { "set-font",                   0x016b, 0, NULL, NULL },
                    619:                { "char-height",                0x016c, 0, NULL, NULL },
                    620:                { "char-width",                 0x016d, 0, NULL, NULL },
                    621:                { ">font",                      0x016e, 0, NULL, NULL },
                    622:                { "fontbytes",                  0x016f, 0, NULL, NULL },
                    623:                { "fb8-draw-character",         0x0180, 0, NULL, NULL },
                    624:                { "fb8-reset-screen",           0x0181, 0, NULL, NULL },
                    625:                { "fb8-toggle-cursor",          0x0182, 0, NULL, NULL },
                    626:                { "fb8-erase-screen",           0x0183, 0, NULL, NULL },
                    627:                { "fb8-blink-screen",           0x0184, 0, NULL, NULL },
                    628:                { "fb8-invert-screen",          0x0185, 0, NULL, NULL },
                    629:                { "fb8-insert-characters",      0x0186, 0, NULL, NULL },
                    630:                { "fb8-delete-characters",      0x0187, 0, NULL, NULL },
                    631:                { "fb8-inisert-lines",          0x0188, 0, NULL, NULL },
                    632:                { "fb8-delete-lines",           0x0189, 0, NULL, NULL },
                    633:                { "fb8-draw-logo",              0x018a, 0, NULL, NULL },
                    634:                { "fb8-install",                0x018b, 0, NULL, NULL },
                    635:                { "return-buffer",              0x01a0, 0, NULL, NULL },
                    636:                { "xmit-packet",                0x01a1, 0, NULL, NULL },
                    637:                { "poll-packet",                0x01a2, 0, NULL, NULL },
                    638:                { "mac-address",                0x01a4, 0, NULL, NULL },
                    639:                { "device-name",                0x0201, 0, NULL, NULL },
                    640:                { "my-args",                    0x0202, 0, NULL, NULL },
                    641:                { "my-self",                    0x0203, 0, NULL, NULL },
                    642:                { "find-package",               0x0204, 0, NULL, NULL },
                    643:                { "open-package",               0x0205, 0, NULL, NULL },
                    644:                { "close-package",              0x0206, 0, NULL, NULL },
                    645:                { "find-method",                0x0207, 0, NULL, NULL },
                    646:                { "call-package",               0x0208, 0, NULL, NULL },
                    647:                { "$call-parent",               0x0209, 0, NULL, NULL },
                    648:                { "my-parent",                  0x020a, 0, NULL, NULL },
                    649:                { "ihandle>phandle",            0x020b, 0, NULL, NULL },
                    650:                { "my-unit",                    0x020d, 0, NULL, NULL },
                    651:                { "$call-method",               0x020e, 0, NULL, NULL },
                    652:                { "$open-package",              0x020f, 0, NULL, NULL },
                    653:                { "processor-type",             0x0210, 0, NULL, NULL },
                    654:                { "firmware-version",           0x0211, 0, NULL, NULL },
                    655:                { "fcode-version",              0x0212, 0, NULL, NULL },
                    656:                { "alarm",                      0x0213, 0, NULL, NULL },
                    657:                { "(is-user-word)",             0x0214, 0, NULL, NULL },
                    658:                { "suspend-fcode",              0x0215, 0, NULL, NULL },
                    659:                { "abort",                      0x0216, 0, NULL, NULL },
                    660:                { "catch",                      0x0217, 0, NULL, NULL },
                    661:                { "throw",                      0x0218, 0, NULL, NULL },
                    662:                { "user-abort",                 0x0219, 0, NULL, NULL },
                    663:                { "get-my-property",            0x021a, 0, NULL, NULL },
                    664:                { "decode-int",                 0x021b, 0, NULL, NULL },
                    665:                { "decode-string",              0x021c, 0, NULL, NULL },
                    666:                { "get-inherited-property",     0x021d, 0, NULL, NULL },
                    667:                { "delete-property",            0x021e, 0, NULL, NULL },
                    668:                { "get-package-property",       0x021f, 0, NULL, NULL },
                    669:                { "cpeek",                      0x0220, 0, NULL, NULL },
                    670:                { "wpeek",                      0x0221, 0, NULL, NULL },
                    671:                { "lpeek",                      0x0222, 0, NULL, NULL },
                    672:                { "cpoke",                      0x0223, 0, NULL, NULL },
                    673:                { "wpoke",                      0x0224, 0, NULL, NULL },
                    674:                { "lpoke",                      0x0225, 0, NULL, NULL },
                    675:                { "lwflip",                     0x0226, 0, NULL, NULL },
                    676:                { "lbflip",                     0x0227, 0, NULL, NULL },
                    677:                { "lbflips",                    0x0228, 0, NULL, NULL },
                    678:                { "adr-mask",                   0x0229, 0, NULL, NULL },
                    679:                { "rb@",                        0x0230, 0, NULL, NULL },
                    680:                { "rb!",                        0x0231, 0, NULL, NULL },
                    681:                { "rw@",                        0x0232, 0, NULL, NULL },
                    682:                { "rw!",                        0x0233, 0, NULL, NULL },
                    683:                { "rl@",                        0x0234, 0, NULL, NULL },
                    684:                { "rl!",                        0x0235, 0, NULL, NULL },
                    685:                { "wbflips",                    0x0236, 0, NULL, NULL },
                    686:                { "lwflips",                    0x0237, 0, NULL, NULL },
                    687:                { "probe",                      0x0238, 0, NULL, NULL },
                    688:                { "probe-virtual",              0x0239, 0, NULL, NULL },
                    689:                { "child",                      0x023b, 0, NULL, NULL },
                    690:                { "peer",                       0x023c, 0, NULL, NULL },
                    691:                { "next-property",              0x023d, 0, NULL, NULL },
                    692:                { "byte-load",                  0x023e, 0, NULL, NULL },
                    693:                { "set-args",                   0x023f, 0, NULL, NULL },
                    694:                { "left-parse-string",          0x0240, 0, NULL, NULL },
1.1       jason     695:                        /* 64-bit FCode extensions */
1.13      otto      696:                { "bxjoin",                     0x0241, 0, NULL, NULL },
                    697:                { "<l@",                        0x0242, 0, NULL, NULL },
                    698:                { "lxjoin",                     0x0243, 0, NULL, NULL },
                    699:                { "rx@",                        0x022e, 0, NULL, NULL },
                    700:                { "rx!",                        0x022f, 0, NULL, NULL },
                    701:                { "wxjoin",                     0x0244, 0, NULL, NULL },
                    702:                { "x,",                         0x0245, 0, NULL, NULL },
                    703:                { "x@",                         0x0246, 0, NULL, NULL },
                    704:                { "x!",                         0x0247, 0, NULL, NULL },
                    705:                { "/x",                         0x0248, 0, NULL, NULL },
                    706:                { "/x*",                        0x0249, 0, NULL, NULL },
                    707:                { "xa+",                        0x024a, 0, NULL, NULL },
                    708:                { "xa1+",                       0x024b, 0, NULL, NULL },
                    709:                { "xbflip",                     0x024c, 0, NULL, NULL },
                    710:                { "xbflips",                    0x024d, 0, NULL, NULL },
                    711:                { "xbsplit",                    0x024e, 0, NULL, NULL },
                    712:                { "xlflip",                     0x024f, 0, NULL, NULL },
                    713:                { "xlflips",                    0x0250, 0, NULL, NULL },
                    714:                { "xlsplit",                    0x0251, 0, NULL, NULL },
                    715:                { "xwflip",                     0x0252, 0, NULL, NULL },
                    716:                { "xwflips",                    0x0253, 0, NULL, NULL },
                    717:                { "xwsplit",                    0x0254, 0, NULL, NULL },
                    718:                { NULL,                         0, 0, NULL, NULL }
1.1       jason     719: };
                    720:
                    721: /*
                    722:  * Default macros -- can be overridden by colon definitions.
                    723:  */
1.13      otto      724: static struct macro macros[] = {
                    725:        { "eval",       "evaluate", 0, NULL, NULL }, /* Build a more balanced tree */
                    726:        { "(.)",        "dup abs <# u#s swap sign u#>", 0, NULL, NULL },
                    727:        { "<<",         "lshift", 0, NULL, NULL },
                    728:        { ">>",         "rshift", 0, NULL, NULL },
                    729:        { "?",          "@ .", 0, NULL, NULL },
                    730:        { "1+",         "1 +", 0, NULL, NULL },
                    731:        { "1-",         "1 -", 0, NULL, NULL },
                    732:        { "2+",         "2 +", 0, NULL, NULL },
                    733:        { "2-",         "2 -", 0, NULL, NULL },
                    734:        { "abort\"",    "-2 throw", 0, NULL, NULL },
                    735:        { "accept",     "span @ -rot expect span @ swap span !", 0, NULL, NULL },
                    736:        { "allot",      "0 max 0 ?do 0 c, loop", 0, NULL, NULL },
                    737:        { "blank",      "bl fill", 0, NULL, NULL },
                    738:        { "/c*",        "chars", 0, NULL, NULL },
                    739:        { "ca1+",       "char+", 0, NULL, NULL },
                    740:        { "carret",     "b(lit) 00 00 00 h# 0d", 0, NULL, NULL },
                    741:        { ".d",         "base @ swap d# 0a base ! . base !", 0, NULL, NULL },
                    742:        { "decode-bytes", ">r over r@ + swap r@ - rot r>", 0, NULL, NULL },
                    743:        { "3drop",      "drop 2drop", 0, NULL, NULL },
                    744:        { "3dup",       "2 pick 2 pick 2 pick", 0, NULL, NULL },
                    745:        { "erase",      "0 fill", 0, NULL, NULL },
                    746:        { "false",      "0", 0, NULL, NULL },
                    747:        { ".h",         "base @ swap d# 10 base ! . base !", 0, NULL, NULL },
                    748:        { "linefeed",   "b(lit) 00 00 00 d# 0a", 0, NULL, NULL },
                    749:        { "/n*",        "cells", 0, NULL, NULL },
                    750:        { "na1+",       "cell+", 0, NULL, NULL },
                    751:        { "not",        "invert", 0, NULL, NULL },
                    752:        { "s.",         "(.) type space", 0, NULL, NULL },
                    753:        { "space",      "bl emit", 0, NULL, NULL },
                    754:        { "spaces",     "0 max 0 ?do space loop", 0, NULL, NULL },
                    755:        { "struct",     "0", 0, NULL, NULL },
                    756:        { "true",       "-1", 0, NULL, NULL },
                    757:        { "(u,)",       "<# u#s u#>", 0, NULL, NULL },
                    758:        { NULL, NULL, 0, NULL, NULL }
1.1       jason     759: };
                    760:
                    761: /*
1.13      otto      762:  * Utility functions.
                    763:  */
                    764:
                    765: /*
                    766:  * ASCII -> long int converter, eats `.'s
                    767:  */
                    768: #define strtol(x, y, z)                cvt(x, y, z)
                    769: static Cell
                    770: cvt(const char *s, char **e, int base)
                    771: {
                    772:        Cell v = 0;
                    773:        int c, n = 0;
                    774:
                    775:        c = *s;
                    776:        if (c == '-') { n = 1; s++; }
                    777:
                    778:        for (c = *s; (c = *s); s++) {
                    779:
                    780:                /* Ignore `.' */
                    781:                if (c == '.')
                    782:                        continue;
                    783:                if (c >= '0' && c <= '9')
                    784:                        c -= '0';
                    785:                else if (c >= 'a' && c <= 'f')
                    786:                        c += 10 - 'a';
                    787:                else if (c >= 'A' && c <= 'F')
                    788:                        c += 10 - 'A';
                    789:                if (c >= base)
                    790:                        break;
                    791:                v *= base;
                    792:                v += c;
                    793:        }
                    794:        if (e)
                    795:                *e = (char *)s;
                    796:        if (n)
                    797:                return (-v);
                    798:        return (v);
                    799: }
                    800:
                    801: /*
1.1       jason     802:  * Parser stack control functions.
                    803:  */
                    804:
1.13      otto      805: static void
                    806: push(Cell val)
1.1       jason     807: {
1.13      otto      808:        if (debug > 1)
                    809:                printf("push %lx\n", (long)val);
1.1       jason     810:        parse_stack[parse_stack_ptr++] = val;
1.13      otto      811:        if (parse_stack_ptr >= PSTKSIZ)
                    812:                errx(EXIT_FAILURE, "Parse stack overflow");
1.1       jason     813: }
                    814:
1.13      otto      815: static Cell
                    816: pop(void)
1.1       jason     817: {
                    818:        ASSERT(parse_stack_ptr);
1.13      otto      819:        if (debug > 1)
                    820:                printf("pop %lx\n", (long)parse_stack[parse_stack_ptr-1]);
1.1       jason     821:        return parse_stack[--parse_stack_ptr];
                    822: }
                    823:
1.13      otto      824: static int
                    825: depth(void)
1.1       jason     826: {
                    827:        return (parse_stack_ptr);
                    828: }
                    829:
                    830: /*
                    831:  * Insert fcode into dictionary.
                    832:  */
1.13      otto      833: static int
                    834: fadd(struct fcode *dict, struct fcode *new)
1.1       jason     835: {
                    836:        int res = strcmp(dict->name, new->name);
                    837:
                    838:        new->type = FCODE;
                    839:        ASSERT(dict->type == FCODE);
1.13      otto      840:        if (!res) {
                    841:                /*
                    842:                 * Duplicate entry.  Give the old name the new FCode
                    843:                 * number.
                    844:                 */
                    845:                dict->num = new->num;
                    846:                return (0);
                    847:        }
1.1       jason     848:        if (res < 0) {
                    849:                if (dict->l)
                    850:                        return fadd(dict->l, new);
                    851:                else {
1.13      otto      852:                        if (debug > 5)
                    853:                                printf("fadd: new FCode `%s' is %lx\n",
1.1       jason     854:                                              new->name, new->num);
                    855:                        new->l = new->r = NULL;
                    856:                        dict->l = new;
                    857:                }
                    858:        } else {
                    859:                if (dict->r)
                    860:                        return fadd(dict->r, new);
                    861:                else {
1.13      otto      862:                        if (debug > 5)
                    863:                                printf("fadd: new FCode `%s' is %lx\n",
1.1       jason     864:                                              new->name, new->num);
                    865:                        new->l = new->r = NULL;
                    866:                        dict->r = new;
                    867:                }
                    868:        }
                    869:        return (1);
                    870: }
                    871:
                    872: /*
                    873:  * Look for a code in the dictionary.
                    874:  */
1.13      otto      875: static struct fcode *
                    876: flookup(struct fcode *dict, const char *str)
1.1       jason     877: {
                    878:        int res;
                    879:        if (!dict) return (dict);
                    880:
                    881:        res = strcmp(dict->name, str);
                    882:        ASSERT(dict->type == FCODE);
1.13      otto      883:        if (debug > 5)
                    884:                printf("flookup: `%s' and `%s' %s match\n",
1.1       jason     885:                              str, dict->name, res?"don't":"do");
                    886:        if (!res) return (dict);
                    887:        if (res < 0)
                    888:                return (flookup(dict->l, str));
                    889:        else
                    890:                return (flookup(dict->r, str));
                    891:
                    892: }
                    893:
                    894: /*
                    895:  * Insert alias into macros.
                    896:  */
1.13      otto      897: static int
                    898: aadd(struct macro *dict, struct macro *new)
1.1       jason     899: {
                    900:        int res = strcmp(dict->name, new->name);
                    901:
                    902:        new->type = MACRO;
                    903:        ASSERT(dict->type == MACRO);
1.13      otto      904:        if (!res) {
                    905:                /* Duplicate name.  Replace the old macro */
                    906:                dict->equiv = new->equiv;
                    907:                /* We can't free the old equiv since it may be static data. */
                    908:                return (0);
                    909:        }
1.1       jason     910:        if (res < 0) {
                    911:                if (dict->l)
                    912:                        return aadd(dict->l, new);
                    913:                else {
                    914:                        new->l = new->r = NULL;
                    915:                        dict->l = new;
1.13      otto      916:                        if (debug > 5)
                    917:                                printf("aadd: new alias `%s' to `%s'\n",
1.1       jason     918:                                              new->name, new->equiv);
                    919:                }
                    920:        } else {
                    921:                if (dict->r)
                    922:                        return aadd(dict->r, new);
                    923:                else {
                    924:                        new->l = new->r = NULL;
                    925:                        dict->r = new;
1.13      otto      926:                        if (debug > 5)
                    927:                                printf("aadd: new alias `%s' to `%s'\n",
1.1       jason     928:                                              new->name, new->equiv);
                    929:                }
                    930:        }
                    931:        return (1);
                    932: }
                    933:
                    934: /*
                    935:  * Look for a macro in the aliases.
                    936:  */
1.13      otto      937: static struct macro *
                    938: alookup(struct macro *dict, const char *str)
1.1       jason     939: {
                    940:        int res;
                    941:        if (!dict) return (dict);
                    942:
                    943:        ASSERT(dict->type == MACRO);
                    944:        res = strcmp(dict->name, str);
                    945:        if (!res) return (dict);
                    946:        if (res < 0)
                    947:                return (alookup(dict->l, str));
                    948:        else
                    949:                return (alookup(dict->r, str));
                    950:
                    951: }
                    952:
                    953: /*
                    954:  * Bootstrap the dictionary and then install
                    955:  * all the standard FCodes.
                    956:  */
1.13      otto      957: static void
                    958: initdic(void)
1.1       jason     959: {
                    960:        struct fcode *code = fcodes;
                    961:        struct macro *alias = macros;
                    962:
                    963:        ASSERT(dictionary == NULL);
                    964:        code->l = code->r = NULL;
                    965:        dictionary = code;
                    966:        code->type = FCODE;
                    967:
                    968:        while ((++code)->name) {
                    969:                if(!fadd(dictionary, code)) {
1.13      otto      970:                        warnx("%s: duplicate dictionary entry `%s'", __func__,
                    971:                            code->name);
1.1       jason     972:                }
                    973:        }
                    974:
                    975:        ASSERT(aliases == NULL);
                    976:        aliases = alias;
                    977:        alias->l = alias->r = NULL;
                    978:        alias->type = MACRO;
                    979:        while ((++alias)->name) {
                    980:                if(!aadd(aliases, alias)) {
1.13      otto      981:                        warnx("%s: duplicate macro entry `%s'", __func__,
                    982:                            alias->name);
1.1       jason     983:                }
                    984:        }
                    985:
                    986: }
                    987:
1.13      otto      988: static int
                    989: apply_macros(YY_BUFFER_STATE yinput, const char *str)
1.1       jason     990: {
                    991:        struct macro *xform = alookup(aliases, str);
                    992:
                    993:        if (xform) {
                    994:                YY_BUFFER_STATE newbuf;
                    995:
1.13      otto      996:                if (debug > 1)
                    997:                        printf("Expanding %s to %s\n", str, xform->equiv);
                    998:
1.1       jason     999:                newbuf = yy_scan_string(xform->equiv);
                   1000:                yy_switch_to_buffer(newbuf);
                   1001:                tokenize(newbuf);
1.13      otto     1002:                yy_switch_to_buffer(yinput);
1.1       jason    1003:                yy_delete_buffer(newbuf);
                   1004:        }
                   1005:        return (xform != NULL);
                   1006: }
                   1007:
1.13      otto     1008: static void
                   1009: usage(void)
1.1       jason    1010: {
1.13      otto     1011:        (void)fprintf(stderr, "%s: [-d level] [-o outfile] <infile>\n",
                   1012:        getprogname());
                   1013:        exit(EXIT_FAILURE);
1.1       jason    1014: }
                   1015:
                   1016: int
1.13      otto     1017: main(int argc, char *argv[])
1.1       jason    1018: {
1.13      otto     1019:        int ch;
1.1       jason    1020:        FILE *inf;
                   1021:        struct fcode_header *fheader;
                   1022:        YY_BUFFER_STATE inbuf;
1.13      otto     1023:        const char *hdrtype = "version1";
1.1       jason    1024:        int i;
1.11      deraadt  1025:
1.1       jason    1026:        outf = 1; /* stdout */
                   1027:
                   1028:        while ((ch = getopt(argc, argv, "d:o:")) != -1)
                   1029:                switch(ch) {
                   1030:                case 'd':
1.13      otto     1031:                        mark_fload = 1;
1.1       jason    1032:                        debug = atol(optarg);
                   1033:                        break;
                   1034:                case 'o':
                   1035:                        outfile = optarg;
                   1036:                        break;
                   1037:                default:
1.13      otto     1038:                        usage();
1.1       jason    1039:                }
                   1040:        argc -= optind;
                   1041:        argv += optind;
                   1042:
                   1043:        if (argc != 1)
1.13      otto     1044:                usage();
1.1       jason    1045:
                   1046:        infile = argv[0];
                   1047:
                   1048:        /*
                   1049:         * Initialization stuff.
                   1050:         */
                   1051:        initdic();
                   1052:        outbufsiz = BUFCLICK;
1.13      otto     1053:        fheader = emalloc(outbufsiz);
                   1054:        outbuf = (void *)fheader;
1.1       jason    1055:        outpos = 0;
                   1056:        emit(hdrtype);
                   1057:        outpos = sizeof(*fheader);
                   1058:
                   1059:        /*
                   1060:         * Do it.
                   1061:         */
                   1062:        if ((inf = fopen(infile, "r")) == NULL)
1.13      otto     1063:                err(EXIT_FAILURE, "Cannot open `%s'", infile);
1.1       jason    1064:
1.13      otto     1065:        inbuf = yy_create_buffer(inf, YY_BUF_SIZE);
1.1       jason    1066:        yy_switch_to_buffer(inbuf);
                   1067:        tokenize(inbuf);
                   1068:        yy_delete_buffer(inbuf);
                   1069:        fclose(inf);
1.13      otto     1070:        if (need_end0) emit("end0");
1.1       jason    1071:
                   1072:        /* Now calculate length and checksum and stick them in the header */
                   1073:        fheader->format = 0x08;
                   1074:        fheader->length = htonl(outpos);
                   1075:        fheader->checksum = 0;
                   1076:        for (i = sizeof(*fheader); i<outpos; i++)
1.13      otto     1077:                fheader->checksum += (unsigned char)outbuf[i];
1.1       jason    1078:        fheader->checksum = htons(fheader->checksum);
                   1079:
1.4       jason    1080:        if ((outf = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1)
1.13      otto     1081:                err(EXIT_FAILURE, "Cannot open `%s'", outfile);
1.1       jason    1082:
                   1083:        if (write(outf, outbuf, outpos) != outpos) {
1.13      otto     1084:                int serrno = errno;
1.1       jason    1085:                close(outf);
                   1086:                unlink(outfile);
1.13      otto     1087:                errc(EXIT_FAILURE, serrno, "write error");
1.1       jason    1088:        }
                   1089:        close(outf);
1.13      otto     1090:        return EXIT_SUCCESS;
1.1       jason    1091: };
                   1092:
                   1093: /*
                   1094:  * Tokenize one file.  This is a separate function so it can
1.15    ! jmc      1095:  * be called recursively to parse multiple levels of include files.
1.1       jason    1096:  */
                   1097:
1.13      otto     1098: static void
                   1099: tokenize(YY_BUFFER_STATE yinput)
1.1       jason    1100: {
                   1101:        FILE *inf;
                   1102:        YY_BUFFER_STATE inbuf;
                   1103:        TOKEN *token;
1.13      otto     1104:        const char *last_token = "";
1.1       jason    1105:        struct fcode *fcode;
                   1106:        int pos, off;
                   1107:
                   1108:        while ((token = yylex()) != NULL) {
                   1109:                switch (token->type) {
                   1110:                case TOK_NUMBER:
                   1111:                        STATE(token->text, "TOK_NUMBER");
                   1112:                {
                   1113:                        char *end;
                   1114:                        Cell value;
                   1115:
                   1116:                        if (tokenizer) {
                   1117:                                push(strtol(token->text, &end, 16));
                   1118:                                break;
                   1119:                        }
1.13      otto     1120:                        value = strtol(token->text, &end, numbase);
1.1       jason    1121:                        if (*end != 0)
                   1122:                                token_err(yylineno, infile, yytext,
                   1123:                                    "illegal number conversion");
                   1124:
                   1125:                        /*
                   1126:                         * If this is a 64-bit value we need to store two literals
                   1127:                         * and issue a `lxjoin' to combine them.  But that's a future
                   1128:                         * project.
                   1129:                         */
                   1130:                        emit("b(lit)");
1.13      otto     1131:                        spit((value>>24)&0x0ff);
1.1       jason    1132:                        spit((value>>16)&0x0ff);
                   1133:                        spit((value>>8)&0x0ff);
                   1134:                        spit(value&0x0ff);
1.13      otto     1135:                        if ((value>>32) != value && (value>>32) != 0 &&
                   1136:                                (value>>32) != -1) {
                   1137:                                emit("b(lit)");
                   1138:                                spit((value>>56)&0x0ff);
                   1139:                                spit((value>>48)&0x0ff);
                   1140:                                spit((value>>40)&0x0ff);
                   1141:                                spit((value>>32)&0x0ff);
                   1142:                                emit("lxjoin");
                   1143:                        }
1.1       jason    1144:                }
                   1145:                break;
                   1146:                case TOK_C_LIT:
                   1147:                        STATE(token->text, "TOK_C_LIT");
                   1148:                        emit("b(lit)");
                   1149:                        spit(0);
                   1150:                        spit(0);
                   1151:                        spit(0);
                   1152:                        spit(token->text[1]);
                   1153:                break;
                   1154:                case TOK_STRING_LIT:
                   1155:                        STATE(token->text, "TOK_STRING_LIT:");
                   1156:                {
1.13      otto     1157:                        size_t len;
1.1       jason    1158:                        char *p = token->text;
                   1159:
                   1160:                        ++p;                    /* Skip the quote */
                   1161:                        len = strlen(++p);      /* Skip the 1st space */
                   1162:
                   1163: #define ERR_TOOLONG    \
1.13      otto     1164:        token_err(yylineno, infile, yytext, "string length %zu too long", len)
1.1       jason    1165:
                   1166:                        if (len > 255)
                   1167:                                ERR_TOOLONG;
                   1168:
                   1169:                        if (p[len-1] == ')' ||
                   1170:                            p[len-1] == '"') {
                   1171:                                p[len-1] = 0;
                   1172:                        }
                   1173:                        emit("b(\")");
                   1174:                        sspit(p);
                   1175:                }
                   1176:                break;
                   1177:                case TOK_PSTRING:
                   1178:                        STATE(token->text, "TOK_PSTRING:");
                   1179:                {
1.13      otto     1180:                        size_t len;
1.1       jason    1181:                        char *p = token->text;
                   1182:
                   1183:                        if (*p++ == '.') p++; /* Skip over delimiter */
                   1184:                        p++; /* Skip over space/tab */
                   1185:
                   1186:                        len = strlen(p);
                   1187:                        if (len > 255)
                   1188:                                ERR_TOOLONG;
                   1189:
                   1190:                        if (p[len-1] == ')' ||
                   1191:                            p[len-1] == '"') {
                   1192:                                p[len-1] = 0;
                   1193:                        }
                   1194:                        emit("b(\")");
                   1195:                        sspit(p);
                   1196:                        emit("type");
                   1197:                }
                   1198:                break;
1.13      otto     1199:                case TOK_ABORT_S:
                   1200:                        STATE(token->text, "TOK_PSTRING:");
                   1201:                {
                   1202:                        size_t len;
                   1203:                        Cell value = -2;
                   1204:                        char *p = token->text;
                   1205:
                   1206:                        while (*p++ != ' '); /* Skip to the string */
                   1207:
                   1208:                        len = strlen(p);
                   1209:                        if (len > 255)
                   1210:                                ERR_TOOLONG;
                   1211:
                   1212:                        if (p[len-1] == '"') {
                   1213:                                p[len-1] = 0;
                   1214:                        }
                   1215:                        emit("b?branch");
                   1216:                        push(outpos);
                   1217:                        offspit(0);
                   1218:                        emit("b(\")");
                   1219:                        sspit(p);
                   1220:                        emit("type");
                   1221:                        emit("cr");
                   1222:                        emit("b(lit)");
                   1223:                        spit((value>>24)&0x0ff);
                   1224:                        spit((value>>16)&0x0ff);
                   1225:                        spit((value>>8)&0x0ff);
                   1226:                        spit(value&0x0ff);
                   1227:                        emit("throw");
                   1228:                        emit("b(>resolve)");
                   1229:                        pos = outpos;
                   1230:                        outpos = pop();
                   1231:                        off = pos - outpos;
                   1232:                        offspit(off);
                   1233:                        outpos = pos;
                   1234:                }
                   1235:                break;
                   1236:
1.1       jason    1237:                case TOK_TOKENIZE:
                   1238:                        STATE(token->text, "TOK_TOKENIZE");
                   1239:                        /* The next pass should tokenize the FCODE number */
                   1240:                        emit("b(')");
                   1241:                        break;
                   1242:                case TOK_COMMENT:
                   1243:                        STATE(token->text, "TOK_COMMENT:");
1.13      otto     1244:                        do {
                   1245:                                off = input();
                   1246:                        } while ((off != ')') && (off != '\n') &&
                   1247:                                (off != EOF));
1.1       jason    1248:                        break;
                   1249:                case TOK_COLON:
                   1250:                        STATE(token->text, "TOK_COLON:");
                   1251:
                   1252:                        token = yylex();
                   1253:                        if (token == NULL)
                   1254:                                token_err(yylineno, infile, yytext,
                   1255:                                    "EOF in colon definition");
                   1256:
                   1257:                        /* Add new code to dictionary */
1.13      otto     1258:                        fcode = emalloc(sizeof(*fcode));
1.1       jason    1259:                        fcode->num = nextfcode++;
1.13      otto     1260:                        fcode->name = estrdup(token->text);
                   1261:                        if (!fadd(dictionary, fcode)) {
                   1262:                                /* Duplicate definition.  Free the memory. */
                   1263:                                if (debug)
                   1264:                                        printf("%s: duplicate FCode\n",
                   1265:                                                token->text);
                   1266:                                free((void *)fcode->name);
                   1267:                                free(fcode);
                   1268:                        }
1.1       jason    1269:                        if (debug)
1.13      otto     1270:                                printf("Adding %s to dictionary\n", token->text);
1.1       jason    1271:                        if (state == 0)
                   1272:                                emit("new-token");
                   1273:                        else {
                   1274:                                if (state == TOK_EXTERNAL)
                   1275:                                        emit("external-token");
                   1276:                                else
                   1277:                                /* Here we have a choice of new-token or named-token */
                   1278:                                        emit("named-token");
                   1279:                                sspit(token->text);
                   1280:                        }
                   1281:                        spit(fcode->num);
                   1282:                        emit("b(:)");
                   1283:                        last_token = fcode->name;
                   1284:                        defining = 1;
                   1285:                        break;
                   1286:                case TOK_SEMICOLON:
                   1287:                        STATE(token->text, "TOK_SEMICOLON:");
                   1288:                        emit("b(;)");
                   1289:                        defining = 0;
                   1290:                        if (depth()) {
                   1291:                                token_err(yylineno, infile, NULL,
                   1292:                                    "Warning: stack depth %d at end of %s\n",
                   1293:                                    depth(), last_token);
                   1294:                        }
                   1295:                        last_token = "";
                   1296:                        break;
                   1297:
                   1298:                        /* These are special */
                   1299:                case TOK_AGAIN:
                   1300:                        STATE(token->text, "TOK_AGAIN");
                   1301:                        emit("bbranch");
                   1302:                        pos = pop();
1.13      otto     1303:                        pos = pos - outpos;
                   1304:                        offspit(pos);
1.1       jason    1305:                        break;
                   1306:                case TOK_ALIAS:
                   1307:                        STATE(token->text, "TOK_ALIAS");
                   1308:                {
                   1309:                        struct macro *alias;
                   1310:
                   1311:                        token = yylex();
                   1312:                        if (token == NULL) {
1.13      otto     1313:                                warnx("EOF in alias definition");
1.1       jason    1314:                                return;
                   1315:                        }
                   1316:                        if (token->type != TOK_OTHER) {
1.13      otto     1317:                                warnx("ENDCOMMENT aliasing weird token type %d",
                   1318:                                    token->type);
1.1       jason    1319:                        }
1.13      otto     1320:                        alias = emalloc(sizeof(*alias));
                   1321:                        alias->name = estrdup(token->text);
1.1       jason    1322:                        token = yylex();
                   1323:                        if (token == NULL) {
1.13      otto     1324:                                warnx("EOF in alias definition");
                   1325:                                free((void *)alias->name);
1.9       deraadt  1326:                                free(alias);
1.1       jason    1327:                                return;
                   1328:                        }
1.13      otto     1329:                        alias->equiv = estrdup(token->text);
1.1       jason    1330:                        if (!aadd(aliases, alias)) {
1.13      otto     1331:                                free((void *)alias->name);
                   1332:                                free(alias);
1.1       jason    1333:                        }
                   1334:                }
                   1335:                break;
                   1336:                case TOK_GETTOKEN:
                   1337:                        STATE(token->text, "TOK_GETTOKEN");
                   1338:                        /* This is caused by ['] */
                   1339:                        emit("b(')");
                   1340:                        token = yylex();
                   1341:                        if (token == NULL) {
1.13      otto     1342:                                warnx("EOF in [']");
1.1       jason    1343:                                return;
                   1344:                        }
1.13      otto     1345:                        if ((fcode = flookup(dictionary, token->text)) == NULL)
                   1346:                                errx(EXIT_FAILURE, "[']: %s not found",
                   1347:                                    token->text);
1.1       jason    1348:                        spit(fcode->num);
                   1349:                        break;
                   1350:                case TOK_ASCII:
                   1351:                        STATE(token->text, "TOK_ASCII");
                   1352:                        token = yylex();
1.13      otto     1353:                        if (token == NULL)
                   1354:                                errx(EXIT_FAILURE, "EOF after \"ascii\"");
1.1       jason    1355:                        emit("b(lit)");
                   1356:                        spit(0);
                   1357:                        spit(0);
                   1358:                        spit(0);
                   1359:                        spit(token->text[0]);
                   1360:                        break;
                   1361:                case TOK_BEGIN:
                   1362:                        STATE(token->text, "TOK_BEGIN");
                   1363:                        emit("b(<mark)");
                   1364:                        push(outpos);
                   1365:                        break;
                   1366:                case TOK_BUFFER:
                   1367:                        STATE(token->text, "TOK_BUFFER");
                   1368:
                   1369:                        token = yylex();
                   1370:                        if (token == NULL) {
1.13      otto     1371:                                warnx("EOF in colon definition");
1.1       jason    1372:                                return;
                   1373:                        }
                   1374:
                   1375:                        /* Add new code to dictionary */
1.13      otto     1376:                        fcode = emalloc(sizeof(*fcode));
1.1       jason    1377:                        fcode->num = nextfcode++;
1.13      otto     1378:                        fcode->name = estrdup(token->text);
1.1       jason    1379:                        fadd(dictionary, fcode);
                   1380:
                   1381:                        if (state == 0)
                   1382:                                emit("new-token");
                   1383:                        else {
                   1384:                                if (state == TOK_EXTERNAL)
                   1385:                                        emit("external-token");
                   1386:                                else
                   1387:                                /* Here we have a choice of new-token or named-token */
                   1388:                                        emit("named-token");
                   1389:                                sspit(token->text);
                   1390:                        }
                   1391:                        spit(fcode->num);
                   1392:                        emit("b(buffer:)");
                   1393:                        break;
                   1394:                case TOK_CASE:
                   1395:                        STATE(token->text, "TOK_CASE");
                   1396:                        emit("b(case)");
                   1397:                        push(0);
                   1398:                        break;
                   1399:                case TOK_CONSTANT:
                   1400:                        STATE(token->text, "TOK_CONSTANT");
                   1401:
                   1402:                        token = yylex();
                   1403:                        if (token == NULL) {
1.13      otto     1404:                                warnx("EOF in constant definition");
1.1       jason    1405:                                return;
                   1406:                        }
                   1407:
                   1408:                        /* Add new code to dictionary */
1.13      otto     1409:                        fcode = emalloc(sizeof(*fcode));
1.1       jason    1410:                        fcode->num = nextfcode++;
1.13      otto     1411:                        fcode->name = estrdup(token->text);
1.1       jason    1412:                        fadd(dictionary, fcode);
                   1413:
                   1414:                        if (state == 0)
                   1415:                                emit("new-token");
                   1416:                        else {
                   1417:                                if (state == TOK_EXTERNAL)
                   1418:                                        emit("external-token");
                   1419:                                else
                   1420:                                /* Here we have a choice of new-token or named-token */
                   1421:                                        emit("named-token");
                   1422:                                sspit(token->text);
                   1423:                        }
                   1424:                        spit(fcode->num);
                   1425:                        emit("b(constant)");
                   1426:                        break;
                   1427:                case TOK_CONTROL:
                   1428:                        STATE(token->text, "TOK_CONTROL");
                   1429:                        token = yylex();
1.13      otto     1430:                        if (token == NULL)
                   1431:                                errx(EXIT_FAILURE, "EOF after \"ascii\"");
1.1       jason    1432:                        emit("b(lit)");
                   1433:                        spit(0);
                   1434:                        spit(0);
                   1435:                        spit(0);
                   1436:                        spit(token->text[0]&0x1f);
                   1437:                        break;
                   1438:                case TOK_CREATE:
                   1439:                        STATE(token->text, "TOK_CREATE");
                   1440:                        /* Don't know what this does or if it's right */
                   1441:                        token = yylex();
                   1442:                        if (token == NULL) {
1.13      otto     1443:                                warnx("EOF in create definition");
1.1       jason    1444:                                return;
                   1445:                        }
                   1446:
                   1447:                        /* Add new code to dictionary */
1.13      otto     1448:                        fcode = emalloc(sizeof(*fcode));
1.1       jason    1449:                        fcode->num = nextfcode++;
1.13      otto     1450:                        fcode->name = estrdup(token->text);
1.1       jason    1451:                        fadd(dictionary, fcode);
                   1452:
                   1453:                        if (state == 0)
                   1454:                                emit("new-token");
                   1455:                        else {
                   1456:                                if (state == TOK_EXTERNAL)
                   1457:                                        emit("external-token");
                   1458:                                else
                   1459:                                /* Here we have a choice of new-token or named-token */
                   1460:                                        emit("named-token");
                   1461:                                sspit(token->text);
                   1462:                        }
                   1463:                        spit(fcode->num);
                   1464:                        emit("b(create)");
                   1465:                        break;
                   1466:                case TOK_DECIMAL:
                   1467:                        STATE(token->text, "TOK_DECIMAL");
                   1468:                        if (token->text[1] != '#') {
                   1469:                                if (defining) {
1.13      otto     1470:                                        emit("b(lit)");
                   1471:                                        spit(0);
                   1472:                                        spit(0);
                   1473:                                        spit(0);
1.1       jason    1474:                                        spit(10);
                   1475:                                        emit("base");
                   1476:                                        emit("!");
                   1477:                                } else
1.13      otto     1478:                                        numbase = TOK_DECIMAL;
1.1       jason    1479:                        } else {
                   1480:                                char *end;
                   1481:                                Cell value;
                   1482:
                   1483:                                token = yylex();
                   1484:                                if (token == NULL) {
1.13      otto     1485:                                        warnx("EOF after d#");
1.1       jason    1486:                                        return;
                   1487:                                }
                   1488:                                if (token->type == TOK_OTHER) {
                   1489:                                        if (strcmp("-1", token->text) == 0) {
                   1490:                                                emit(token->text);
                   1491:                                                break;
                   1492:                                        }
                   1493:                                }
                   1494:                                value = strtol(token->text, &end, 10);
                   1495:                                if (*end != 0)
                   1496:                                        token_err(yylineno, infile, NULL,
                   1497:                                            "Illegal number conversion: %s", token->text);
                   1498:
                   1499:                                /*
                   1500:                                 * If this is a 64-bit value we need to store two literals
                   1501:                                 * and issue a `lxjoin' to combine them.  But that's a future
                   1502:                                 * project.
                   1503:                                 */
                   1504:                                emit("b(lit)");
1.13      otto     1505:                                spit((value>>24)&0x0ff);
1.1       jason    1506:                                spit((value>>16)&0x0ff);
                   1507:                                spit((value>>8)&0x0ff);
                   1508:                                spit(value&0x0ff);
1.13      otto     1509:                                if ((value>>32) != value && (value>>32) != 0) {
                   1510:                                        emit("b(lit)");
                   1511:                                        spit((value>>56)&0x0ff);
                   1512:                                        spit((value>>48)&0x0ff);
                   1513:                                        spit((value>>40)&0x0ff);
                   1514:                                        spit((value>>32)&0x0ff);
                   1515:                                        emit("lxjoin");
                   1516:                                }
1.1       jason    1517:                        }
                   1518:                        break;
                   1519:                case TOK_DEFER:
                   1520:                        STATE(token->text, "TOK_DEFER");
                   1521:                        /* Don't know what this does or if it's right */
                   1522:                        token = yylex();
                   1523:                        if (token == NULL) {
1.13      otto     1524:                                warnx("EOF in colon definition");
1.1       jason    1525:                                return;
                   1526:                        }
                   1527:
                   1528:                        /* Add new code to dictionary */
1.13      otto     1529:                        fcode = emalloc(sizeof(*fcode));
1.1       jason    1530:                        fcode->num = nextfcode++;
1.13      otto     1531:                        fcode->name = estrdup(token->text);
1.1       jason    1532:                        fadd(dictionary, fcode);
                   1533:
                   1534:                        if (state == 0)
                   1535:                                emit("new-token");
                   1536:                        else {
                   1537:                                if (state == TOK_EXTERNAL)
                   1538:                                        emit("external-token");
                   1539:                                else
                   1540:                                /* Here we have a choice of new-token or named-token */
                   1541:                                        emit("named-token");
                   1542:                                sspit(token->text);
                   1543:                        }
                   1544:                        spit(fcode->num);
                   1545:                        emit("b(defer)");
                   1546:                        break;
                   1547:                case TOK_DO:
                   1548:                        STATE(token->text, "TOK_DO");
                   1549:                        /*
                   1550:                         * From the 1275 spec.  B is branch location, T is branch target.
                   1551:                         *
                   1552:                         *      b(do)  offset1 ... b(loop)  offset2 ...
                   1553:                         *      b(do)  offset1 ... b(+loop) offset2 ...
                   1554:                         *      b(?do) offset1 ... b(loop)  offset2 ...
                   1555:                         *      b(?do) offset1 ... b(+loop) offset2 ...
                   1556:                         *            ^                            ^
                   1557:                         *           B1       ^            ^       T1
                   1558:                         *                    T2           B2
                   1559:                         *
                   1560:                         * How we do this is we generate the b(do) or b(?do), spit out a
                   1561:                         * zero offset while remembering b1 and t2.  Then we call tokenize()
                   1562:                         * to generate the body.  When tokenize() finds a b(loop) or b(+loop),
                   1563:                         * it generates the FCode and returns, with outpos at b2.  We then
                   1564:                         * calculate the offsets, put them in the right slots and finishup.
                   1565:                         */
                   1566:
                   1567:                        if (token->text[0] == '?')
                   1568:                                emit("b(?do)");
                   1569:                        else
                   1570:                                emit("b(do)");
                   1571:                        push(outpos);
1.13      otto     1572:                        offspit(0);     /* Place holder for later */
1.1       jason    1573:                        push(outpos);
                   1574:                        break;
1.13      otto     1575:                case TOK_END0:
                   1576:                        STATE(token->text, "TOK_END0");
                   1577:                        emit("end0");
                   1578:                        /* Remember we already generated end0 */
                   1579:                        need_end0 = 0;
                   1580:                        break;
1.1       jason    1581:                case TOK_ELSE:
                   1582:                        STATE(token->text, "TOK_ELSE");
                   1583:                        /* Get where we need to patch */
                   1584:                        off = pop();
                   1585:                        emit("bbranch");
                   1586:                        /* Save where we are now. */
                   1587:                        push(outpos);
1.13      otto     1588:                        offspit(0);     /* Place holder for later */
1.1       jason    1589:                        emit("b(>resolve)");
                   1590:                        /* Rewind and patch the if branch */
                   1591:                        pos = outpos;
                   1592:                        outpos = off;
                   1593:                        off = pos - off;
1.13      otto     1594:                        offspit(off);   /* Place holder for later */
1.1       jason    1595:                        /* revert to the end */
                   1596:                        outpos = pos;
                   1597:                        break;
                   1598:                case TOK_ENDCASE:
                   1599:                        STATE(token->text, "TOK_ENDCASE:");
1.13      otto     1600:                        emit("b(endcase)");
1.1       jason    1601:                        pos = outpos; /* Remember where we need to branch to */
                   1602:
                   1603:                        /* Thread our way backwards and install proper offsets */
                   1604:                        off = pop();
                   1605:                        while (off) {
1.13      otto     1606:                                int disp;
                   1607:                                int next;
1.1       jason    1608:
                   1609:                                /* Move to this offset */
                   1610:                                outpos = off;
                   1611:                                /* Load next offset to process */
1.13      otto     1612:                                disp = (signed char)(outbuf[outpos]);
                   1613:                                if (offsetsize == 16) {
                   1614:                                        disp = (disp << 8) |
                   1615:                                                (unsigned char)outbuf[outpos+1];
                   1616:                                }
                   1617:                                next = outpos + disp;
                   1618:                                if (debug > -3)
                   1619:                                        printf("Next endof: %x at %x\n",
                   1620:                                            disp, next);
1.1       jason    1621:
                   1622:                                /* process this offset */
                   1623:                                off = pos - outpos;
1.13      otto     1624:                                offspit(off);
                   1625:                                if ((off = disp))
                   1626:                                        off = next;
1.1       jason    1627:                        }
                   1628:                        outpos = pos;
                   1629:                        break;
                   1630:                case TOK_ENDOF:
                   1631:                        STATE(token->text, "TOK_ENDOF");
                   1632:                        off = pop();
                   1633:                        emit("b(endof)");
                   1634:                        /*
                   1635:                         * Save back pointer in the offset field so we can traverse
                   1636:                         * the linked list and patch it in the endcase.
                   1637:                         */
                   1638:                        pos = pop();    /* get position of prev link. */
                   1639:                        push(outpos);   /* save position of this link. */
1.13      otto     1640:                        if (pos)
                   1641:                                /* save potision of prev link. */
                   1642:                                offspit(pos - outpos);
                   1643:                        else
                   1644:                                /* This is the first statement */
                   1645:                                offspit(0);
1.1       jason    1646:                        pos = outpos;
                   1647:                        /* Now point the offset from b(of) here. */
                   1648:                        outpos = off;
1.13      otto     1649:                        off = pos - off;
                   1650:                        offspit(off);
1.1       jason    1651:                        /* Restore position */
                   1652:                        outpos = pos;
                   1653:                        break;
                   1654:                case TOK_EXTERNAL:
                   1655:                        STATE(token->text, "TOK_EXTERNAL");
                   1656:                        state = TOK_EXTERNAL;
                   1657:                        break;
1.13      otto     1658:                case TOK_FCODE_VERSION2:
                   1659:                        /* This is actually a tokenizer directive. */
                   1660:                        STATE(token->text, "TOK_FCODE_VERSION2");
                   1661:                        offsetsize = 16;
                   1662:                        pos = outpos;
                   1663:                        outpos = 0;
                   1664:                        emit("start1");
                   1665:                        outpos = pos;
                   1666:                        break;
                   1667:                case TOK_FCODE_END:
                   1668:                        /*
                   1669:                         * Another tokenizer directive.
                   1670:                         *
                   1671:                         * This should generate end0 and finish filling in
                   1672:                         * the FCode header.  But that's all done in main().
                   1673:                         */
                   1674:                        STATE(token->text, "TOK_FCODE_END");
                   1675:                        return;
1.1       jason    1676:                case TOK_FIELD:
                   1677:                        STATE(token->text, "TOK_FIELD");
                   1678:
                   1679:                        token = yylex();
                   1680:                        if (token == NULL) {
1.13      otto     1681:                                warnx("EOF in field definition");
1.1       jason    1682:                                return;
                   1683:                        }
                   1684:
                   1685:                        /* Add new code to dictionary */
1.13      otto     1686:                        fcode = emalloc(sizeof(*fcode));
1.1       jason    1687:                        fcode->num = nextfcode++;
1.13      otto     1688:                        fcode->name = estrdup(token->text);
1.1       jason    1689:                        fadd(dictionary, fcode);
                   1690:
                   1691:                        if (state == 0)
                   1692:                                emit("new-token");
                   1693:                        else {
                   1694:                                if (state == TOK_EXTERNAL)
                   1695:                                        emit("external-token");
                   1696:                                else
                   1697:                                /* Here we have a choice of new-token or named-token */
                   1698:                                        emit("named-token");
                   1699:                                sspit(token->text);
                   1700:                        }
                   1701:                        spit(fcode->num);
                   1702:                        emit("b(field)");
                   1703:                        break;
                   1704:
                   1705:                case TOK_HEX:
                   1706:                        STATE(token->text, "TOK_HEX");
                   1707:                        if (token->text[1] != '#') {
                   1708:                                if (defining) {
1.13      otto     1709:                                        emit("b(lit)");
                   1710:                                        spit(0);
                   1711:                                        spit(0);
                   1712:                                        spit(0);
1.1       jason    1713:                                        spit(16);
                   1714:                                        emit("base");
                   1715:                                        emit("!");
                   1716:                                } else
1.13      otto     1717:                                        numbase = TOK_HEX;
1.1       jason    1718:                        } else {
                   1719:                                char *end;
                   1720:                                Cell value;
                   1721:
                   1722:                                token = yylex();
                   1723:                                if (token == NULL) {
1.13      otto     1724:                                        warnx("EOF after h#");
1.1       jason    1725:                                        return;
                   1726:                                }
                   1727:                                value = strtol(token->text, &end, 16);
1.13      otto     1728:                                if (*end != 0)
                   1729:                                        errx(EXIT_FAILURE, "Illegal number"
                   1730:                                            " conversion:%s:%d: %s\n",
1.1       jason    1731:                                            infile, yylineno, yytext);
                   1732:                                /*
                   1733:                                 * If this is a 64-bit value we need to store two literals
                   1734:                                 * and issue a `lxjoin' to combine them.  But that's a future
                   1735:                                 * project.
                   1736:                                 */
                   1737:                                emit("b(lit)");
1.13      otto     1738:                                spit((value>>24)&0x0ff);
1.1       jason    1739:                                spit((value>>16)&0x0ff);
                   1740:                                spit((value>>8)&0x0ff);
                   1741:                                spit(value&0x0ff);
1.13      otto     1742:                                if ((value>>32) != value && (value>>32) != 0) {
                   1743:                                        emit("b(lit)");
                   1744:                                        spit((value>>56)&0x0ff);
                   1745:                                        spit((value>>48)&0x0ff);
                   1746:                                        spit((value>>40)&0x0ff);
                   1747:                                        spit((value>>32)&0x0ff);
                   1748:                                        emit("lxjoin");
                   1749:                                }
1.1       jason    1750:                        }
                   1751:                        break;
                   1752:                case TOK_HEADERLESS:
                   1753:                        STATE(token->text, "TOK_HEADERLESS");
                   1754:                        state = 0;
                   1755:                        break;
                   1756:                case TOK_HEADERS:
                   1757:                        STATE(token->text, "TOK_HEADERS");
                   1758:                        state = TOK_HEADERS;
                   1759:                        break;
                   1760:                case TOK_IF:
                   1761:                        STATE(token->text, "TOK_IF");
                   1762:                        /*
                   1763:                         * Similar to do but simpler since we only deal w/one branch.
                   1764:                         */
                   1765:                        emit("b?branch");
                   1766:                        push(outpos);
1.13      otto     1767:                        offspit(0);     /* Place holder for later */
1.1       jason    1768:                        break;
                   1769:                case TOK_LEAVE:
                   1770:                        STATE(token->text, "TOK_LEAVE");
                   1771:                        emit("b(leave)");
                   1772:                        break;
                   1773:                case TOK_LOOP:
                   1774:                        STATE(token->text, "TOK_LOOP");
                   1775:
                   1776:                        if (token->text[0] == '+')
                   1777:                                emit("b(+loop)");
                   1778:                        else
                   1779:                                emit("b(loop)");
                   1780:                        /* First do backwards branch of loop */
                   1781:                        pos = pop();
                   1782:                        off = pos - outpos;
1.13      otto     1783:                        offspit(off);
1.1       jason    1784:                        /* Now do forward branch of do */
                   1785:                        pos = outpos;
                   1786:                        outpos = pop();
                   1787:                        off = pos - outpos;
1.13      otto     1788:                        spit(off);
1.1       jason    1789:                        /* Restore output position */
                   1790:                        outpos = pos;
                   1791:                        break;
                   1792:                case TOK_OCTAL:
                   1793:                        STATE(token->text, "TOK_OCTAL");
                   1794:                        if (token->text[1] != '#') {
                   1795:                                if (defining) {
                   1796:                                        spit(16);
                   1797:                                        emit("base");
                   1798:                                        emit("!");
                   1799:                                } else
1.13      otto     1800:                                        numbase = TOK_OCTAL;
1.1       jason    1801:                        } else {
                   1802:                                char *end;
                   1803:                                Cell value;
                   1804:
                   1805:                                token = yylex();
                   1806:                                if (token == NULL) {
1.13      otto     1807:                                        warnx("EOF after o#");
1.1       jason    1808:                                        return;
                   1809:                                }
                   1810:                                value = strtol(token->text, &end, 8);
                   1811:                                if (*end != 0) {
1.13      otto     1812:                                        errx(EXIT_FAILURE, "Illegal number"
                   1813:                                            " conversion:%s:%d: %s\n",
1.1       jason    1814:                                            infile, yylineno, yytext);
                   1815:                                }
                   1816:                                /*
                   1817:                                 * If this is a 64-bit value we need to store two literals
                   1818:                                 * and issue a `lxjoin' to combine them.  But that's a future
                   1819:                                 * project.
                   1820:                                 */
                   1821:                                emit("b(lit)");
1.13      otto     1822:                                spit((value>>24)&0x0ff);
1.1       jason    1823:                                spit((value>>16)&0x0ff);
                   1824:                                spit((value>>8)&0x0ff);
                   1825:                                spit(value&0x0ff);
1.13      otto     1826:                                if ((value>>32) != value && (value>>32) != 0) {
                   1827:                                        emit("b(lit)");
                   1828:                                        spit((value>>56)&0x0ff);
                   1829:                                        spit((value>>48)&0x0ff);
                   1830:                                        spit((value>>40)&0x0ff);
                   1831:                                        spit((value>>32)&0x0ff);
                   1832:                                        emit("lxjoin");
                   1833:                                }
1.1       jason    1834:                        }
                   1835:                        break;
                   1836:                case TOK_OF:
                   1837:                        STATE(token->text, "TOK_OF");
                   1838:                        /*
                   1839:                         * Let's hope I get the semantics right.
                   1840:                         *
                   1841:                         * The `of' behaves almost the same as an
                   1842:                         * `if'.  The difference is that `endof'
                   1843:                         * takes a branch offset to the associated
                   1844:                         * `endcase'.  Here we will generate a temporary
                   1845:                         * offset of the `of' associated with the `endof'.
                   1846:                         * Then in `endcase' we should be pointing just
                   1847:                         * after the offset of the last `endof' so we
                   1848:                         * calculate the offset and thread our way backwards
                   1849:                         * searching for the previous `b(case)' or `b(endof)'.
                   1850:                         */
                   1851:                        emit("b(of)");
                   1852:                        push(outpos);
1.13      otto     1853:                        offspit(0);     /* Place holder for later */
                   1854:                        break;
                   1855:                case TOK_OFFSET16:
                   1856:                        STATE(token->text, "TOK_OFFSET16");
                   1857:                        offsetsize = 16;
                   1858:                        emit("offset16");
1.1       jason    1859:                        break;
                   1860:                case TOK_REPEAT:
                   1861:                        STATE(token->text, "TOK_REPEAT");
                   1862:                        emit("bbranch");
                   1863:                        pos = pop();
                   1864:                        off = pop();
                   1865:                        /* First the offset for the branch back to the begin */
                   1866:                        off -= outpos;
1.13      otto     1867:                        offspit(off);
1.1       jason    1868:                        emit("b(>resolve)");
                   1869:                        /* Now point the offset of the while here. */
                   1870:                        off = outpos;
                   1871:                        outpos = pos;
                   1872:                        pos = off - pos;
1.13      otto     1873:                        offspit(pos);
1.1       jason    1874:                        /* Return to the end of the output */
                   1875:                        outpos = off;
                   1876:                        break;
1.13      otto     1877:                case TOK_STARTX:
                   1878:                        /* Put a "startX" at addr 0. */
                   1879:                        STATE(token->text, "TOK_FCODE_VERSION2");
                   1880:                        offsetsize = 16;
                   1881:                        pos = outpos;
                   1882:                        outpos = 0;
                   1883:                        emit(token->text);
                   1884:                        outpos = pos;
                   1885:                        break;
1.1       jason    1886:                case TOK_THEN:
                   1887:                        STATE(token->text, "TOK_THEN");
                   1888:                        emit("b(>resolve)");
                   1889:                        pos = outpos;
                   1890:                        outpos = pop();
                   1891:                        off = pos - outpos;
1.13      otto     1892:                        offspit(off);
1.1       jason    1893:                        outpos = pos;
                   1894:                        break;
                   1895:                case TOK_TO:
                   1896:                        STATE(token->text, "TOK_TO");
                   1897:                        /* The next pass should tokenize the FCODE number */
                   1898:                        emit("b(to)");
                   1899:                        break;
                   1900:                case TOK_UNTIL:
                   1901:                        STATE(token->text, "TOK_UNTIL");
                   1902:                        emit("b?branch");
                   1903:                        pos = pop();
                   1904:                        pos -= outpos;
1.13      otto     1905:                        offspit(pos);
                   1906:                        break;
1.1       jason    1907:                case TOK_VALUE:
                   1908:                        STATE(token->text, "TOK_VALUE");
                   1909:
                   1910:                        token = yylex();
                   1911:                        if (token == NULL) {
1.13      otto     1912:                                warnx("EOF in value definition");
1.1       jason    1913:                                return;
                   1914:                        }
                   1915:
                   1916:                        /* Add new code to dictionary */
1.13      otto     1917:                        fcode = emalloc(sizeof(*fcode));
1.1       jason    1918:                        fcode->num = nextfcode++;
1.13      otto     1919:                        fcode->name = estrdup(token->text);
1.1       jason    1920:                        fadd(dictionary, fcode);
                   1921:
                   1922:                        if (state == 0)
                   1923:                                emit("new-token");
                   1924:                        else {
                   1925:                                if (state == TOK_EXTERNAL)
                   1926:                                        emit("external-token");
                   1927:                                else
                   1928:                                /* Here we have a choice of new-token or named-token */
                   1929:                                        emit("named-token");
                   1930:                                sspit(token->text);
                   1931:                        }
                   1932:                        spit(fcode->num);
                   1933:                        emit("b(value)");
                   1934:                        break;
                   1935:                case TOK_VARIABLE:
                   1936:                        STATE(token->text, "TOK_VARIABLE");
                   1937:
                   1938:                        token = yylex();
                   1939:                        if (token == NULL) {
1.13      otto     1940:                                warnx("EOF in variable definition");
1.1       jason    1941:                                return;
                   1942:                        }
                   1943:
                   1944:                        /* Add new code to dictionary */
1.13      otto     1945:                        fcode = emalloc(sizeof(*fcode));
1.1       jason    1946:                        fcode->num = nextfcode++;
1.13      otto     1947:                        fcode->name = estrdup(token->text);
1.1       jason    1948:                        fadd(dictionary, fcode);
                   1949:
                   1950:                        if (state == 0)
                   1951:                                emit("new-token");
                   1952:                        else {
                   1953:                                if (state == TOK_EXTERNAL)
                   1954:                                        emit("external-token");
                   1955:                                else
                   1956:                                /* Here we have a choice of new-token or named-token */
                   1957:                                        emit("named-token");
                   1958:                                sspit(token->text);
                   1959:                        }
                   1960:                        spit(fcode->num);
                   1961:                        emit("b(variable)");
                   1962:                        break;
1.13      otto     1963:                case TOK_VERSION1:
                   1964:                        /* This is actually a tokenizer directive. */
                   1965:                        STATE(token->text, "TOK_FCODE_VERSION1");
                   1966:                        offsetsize = 8;
                   1967:                        pos = outpos;
                   1968:                        outpos = 0;
                   1969:                        emit("version1");
                   1970:                        outpos = pos;
                   1971:                        break;
1.1       jason    1972:                case TOK_WHILE:
                   1973:                        STATE(token->text, "TOK_WHILE");
                   1974:                        emit("b?branch");
                   1975:                        push(outpos);
1.13      otto     1976:                        offspit(0);
1.1       jason    1977:                        break;
                   1978:
                   1979:                        /* Tokenizer directives */
                   1980:                case TOK_BEGTOK:
                   1981:                        STATE(token->text, "TOK_BEGTOK");
                   1982:                        tokenizer = 1;
                   1983:                        break;
                   1984:                case TOK_EMIT_BYTE:
                   1985:                        STATE(token->text, "TOK_EMIT_BYTE");
                   1986:                        spit(pop());
                   1987:                        break;
                   1988:                case TOK_ENDTOK:
                   1989:                        STATE(token->text, "TOK_ENDTOK");
                   1990:                        tokenizer = 0;
                   1991:                        break;
                   1992:                case TOK_FLOAD:
                   1993:                        {
                   1994:                                char *oldinfile = infile;
                   1995:
1.13      otto     1996:                                STATE(token->text, "TOK_FLOAD");
                   1997:                                /* Parse a different file for a while */
                   1998:                                token = yylex();
                   1999:                                if ((inf = fopen(token->text, "r")) == NULL) {
                   2000:                                        warn("Cannot open `%s'", token->text);
                   2001:                                        break;
                   2002:                                }
                   2003:                                infile = estrdup(token->text);
                   2004:                                if (mark_fload) {
                   2005:                                        /*
                   2006:                                         * Insert commands to print out the
                   2007:                                         * filename into the instruction
                   2008:                                         * stream
                   2009:                                         */
                   2010:                                        emit("b(\")");
                   2011:                                        sspit("fload-ing ");
                   2012:                                        emit("type");
                   2013:                                        emit("b(\")");
                   2014:                                        sspit(infile);
                   2015:                                        emit("type");
                   2016:                                        emit("cr");
                   2017:                                        emit(".s");
                   2018:                                }
                   2019:                                inbuf = yy_create_buffer(inf, YY_BUF_SIZE);
                   2020:                                yy_switch_to_buffer(inbuf);
                   2021:
                   2022:                                printf("======= fload file %s\n", infile);
1.1       jason    2023:                                tokenize(inbuf);
1.13      otto     2024:                                printf("======= done file %s\n", infile);
                   2025:                                yy_switch_to_buffer(yinput);
                   2026:                                yy_delete_buffer(inbuf);
                   2027:                                fclose(inf);
                   2028:                                if (mark_fload) {
                   2029:                                        /*
                   2030:                                         * Insert commands to print out the
                   2031:                                         * filename into the instruction
                   2032:                                         * stream
                   2033:                                         */
                   2034:                                        emit("b(\")");
                   2035:                                        sspit("fload-ed ");
                   2036:                                        emit("type");
                   2037:                                        emit("b(\")");
                   2038:                                        sspit(infile);
                   2039:                                        emit("type");
                   2040:                                        emit("cr");
                   2041:                                        emit(".s");
                   2042:                                        emit("cr");
                   2043:                                }
                   2044:                                free(infile);
1.1       jason    2045:                                infile = oldinfile;
                   2046:                        }
                   2047:                        break;
                   2048:                case TOK_OTHER:
                   2049:                        STATE(token->text, "TOK_OTHER");
1.13      otto     2050:                        if (apply_macros(yinput, token->text))
1.1       jason    2051:                                break;
                   2052:                        if (emit(token->text)) {
                   2053: #if 0
                   2054:                                /*
                   2055:                                 * Call an external command
                   2056:                                 *
                   2057:                                 * XXXXX assumes it will always find the command
                   2058:                                 */
                   2059:                                sspit(token->text);
                   2060:                                emit("$find");
                   2061:                                emit("drop");
                   2062:                                emit("execute");
                   2063: #else
1.13      otto     2064:                                token_err(yylineno, infile, yytext,
                   2065:                                        "%s: undefined token `%s'\n",
                   2066:                                        myname, token->text);
1.1       jason    2067: #endif
                   2068:                        }
                   2069:                        break;
                   2070:                default:
1.13      otto     2071:                        /* Nothing */ ;
1.1       jason    2072:                }
                   2073:        }
                   2074:        return;
                   2075: }
                   2076:
                   2077: /*
                   2078:  * print a tokenizer error message
                   2079:  */
1.13      otto     2080: static void
                   2081: token_err(int lineno, const char *file, const char *text, const char *fmt, ...)
1.1       jason    2082: {
                   2083:        va_list ap;
                   2084:
                   2085:        va_start(ap, fmt);
1.13      otto     2086:        fprintf(stderr, "%s: ", getprogname());
                   2087:        if (file)
                   2088:                (void)fprintf(stderr, "%s,%d: ", file, lineno);
1.1       jason    2089:        if (fmt)
                   2090:                (void)vfprintf(stderr, fmt, ap);
                   2091:        fputc('\n', stderr);
                   2092:        if (text)
                   2093:                fprintf(stderr, "\t%s", text);
                   2094:        va_end(ap);
1.13      otto     2095:        exit(EXIT_FAILURE);
1.1       jason    2096: }
                   2097:
                   2098: /*
                   2099:  * Lookup fcode string in dictionary and spit it out.
                   2100:  *
                   2101:  * Fcode must be in dictionary.  No alias conversion done.
                   2102:  */
1.13      otto     2103: static int
                   2104: emit(const char *str)
1.1       jason    2105: {
                   2106:        struct fcode *code;
1.13      otto     2107:        if ((code = flookup(dictionary, str)))
1.1       jason    2108:                spit(code->num);
                   2109:        if (debug > 1) {
                   2110:                if (code)
1.13      otto     2111:                        printf("emitting `%s'\n", code->name);
1.1       jason    2112:                else
1.13      otto     2113:                        printf("emit: not found `%s'\n", str);
1.1       jason    2114:        }
                   2115:        return (code == NULL);
                   2116: }
                   2117:
                   2118: /*
                   2119:  * Spit out an integral value as a series of FCodes.
                   2120:  *
                   2121:  * It will spit out one zero byte or as many bytes as are
                   2122:  * non-zero.
                   2123:  */
1.13      otto     2124: static int
                   2125: spit(long n)
1.1       jason    2126: {
                   2127:        int count = 1;
                   2128:
                   2129:        if (n >> 8)
                   2130:                count += spit(n >> 8);
1.13      otto     2131:        if ((size_t)outpos >= outbufsiz) {
                   2132:                while ((size_t)outpos >= outbufsiz) outbufsiz += BUFCLICK;
                   2133:                outbuf = erealloc(outbuf, outbufsiz);
1.1       jason    2134:        }
1.13      otto     2135:        if (debug > 3) printf("%lx: spitting %2.2x\n", outpos, (unsigned char)n);
1.1       jason    2136:        outbuf[outpos++] = n;
                   2137:        return (count);
                   2138: }
                   2139:
                   2140: /*
                   2141:  * Spit out an FCode string.
                   2142:  */
1.13      otto     2143: static void
                   2144: sspit(const char *s)
1.1       jason    2145: {
                   2146:        int len = strlen(s);
                   2147:
                   2148:        if (len > 255) {
1.13      otto     2149:                warnx("string length %d too long", len);
1.1       jason    2150:                return;
                   2151:        }
1.13      otto     2152:        if (debug > 2)
                   2153:                printf("sspit: len %d str `%s'\n", len, s);
1.1       jason    2154:        spit(len);
1.13      otto     2155:        while (len--)
1.1       jason    2156:                spit(*s++);
                   2157: }
                   2158:
1.13      otto     2159: /*
                   2160:  * Spit out an offset.  Offsets can be 8 or 16 bits.
                   2161:  * Bail if the value overflows.  This is a little complicated since
                   2162:  * offsets can be negative numbers.
                   2163:  */
                   2164: static int
                   2165: offspit(long n)
                   2166: {
                   2167:
                   2168:        if (offsetsize == 16) {
                   2169:                volatile int16_t off16 = n;
                   2170:
                   2171:                if (n != off16)
                   2172:                        token_err(yylineno, infile, NULL,
                   2173:                                "Offset16 offset overflow: %lx != %x\n",
                   2174:                                n, off16);
                   2175:                spit((n>>8) & 0xff);
                   2176:                return spit(n & 0xff);
                   2177:        } else {
                   2178:                volatile int8_t off8 = n;
                   2179:
                   2180:                if (n != off8)
                   2181:                        token_err(yylineno, infile, NULL,
                   2182:                                "Offset8 offset overflow: %lx != %x\n",
                   2183:                                n, off8);
                   2184:                return spit(n & 0x0ffL);
                   2185:        }
                   2186: }
                   2187:
1.1       jason    2188: int
1.13      otto     2189: yywrap(void)
1.1       jason    2190: {
                   2191:        /* Always generate EOF */
                   2192:        return (1);
                   2193: }