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