GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/fgen/fgen.l Lines: 0 580 0.0 %
Date: 2017-11-13 Branches: 0 441 0.0 %

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