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