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