[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.13

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