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