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