1 %{ 2 /* $OpenBSD: fgen.l,v 1.9 2009/12/10 17:31:49 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 outf = 1; /* stdout */ 964 myname = argv[0]; 965 966 bflag = 0; 967 while ((ch = getopt(argc, argv, "d:o:")) != -1) 968 switch(ch) { 969 case 'd': 970 debug = atol(optarg); 971 break; 972 case 'o': 973 outfile = optarg; 974 break; 975 case '?': 976 default: 977 warnx("Illegal argument: %c", ch); 978 usage(myname); 979 } 980 argc -= optind; 981 argv += optind; 982 983 if (argc != 1) 984 usage(myname); 985 986 infile = argv[0]; 987 988 /* 989 * Initialization stuff. 990 */ 991 initdic(); 992 outbufsiz = BUFCLICK; 993 outbuf = malloc(outbufsiz); 994 if (outbuf == NULL) 995 (void)err(1, "out of memory"); 996 997 fheader = (struct fcode_header *)outbuf; 998 outpos = 0; 999 emit(hdrtype); 1000 outpos = sizeof(*fheader); 1001 1002 /* 1003 * Do it. 1004 */ 1005 if ((inf = fopen(infile, "r")) == NULL) 1006 (void)err(1, "can not open %s for reading", infile); 1007 1008 inbuf = yy_create_buffer( inf, YY_BUF_SIZE ); 1009 yy_switch_to_buffer(inbuf); 1010 tokenize(inbuf); 1011 yy_delete_buffer(inbuf); 1012 fclose(inf); 1013 emit("end0"); 1014 1015 /* Now calculate length and checksum and stick them in the header */ 1016 fheader->format = 0x08; 1017 fheader->length = htonl(outpos); 1018 fheader->checksum = 0; 1019 for (i = sizeof(*fheader); i<outpos; i++) 1020 fheader->checksum += outbuf[i]; 1021 fheader->checksum = htons(fheader->checksum); 1022 1023 if ((outf = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1) 1024 err(1, "can out open %s for writing", outfile); 1025 1026 if (write(outf, outbuf, outpos) != outpos) { 1027 close(outf); 1028 unlink(outfile); 1029 err(1, "write error"); 1030 } 1031 close(outf); 1032 return (0); 1033 }; 1034 1035 /* 1036 * Tokenize one file. This is a separate function so it can 1037 * be called recursively to parse multiple levels of include files. 1038 */ 1039 1040 void 1041 tokenize(input) 1042 YY_BUFFER_STATE input; 1043 { 1044 FILE *inf; 1045 YY_BUFFER_STATE inbuf; 1046 TOKEN *token; 1047 char *last_token = ""; 1048 struct fcode *fcode; 1049 int pos, off; 1050 1051 while ((token = yylex()) != NULL) { 1052 switch (token->type) { 1053 case TOK_NUMBER: 1054 STATE(token->text, "TOK_NUMBER"); 1055 { 1056 char *end; 1057 Cell value; 1058 1059 if (tokenizer) { 1060 push(strtol(token->text, &end, 16)); 1061 break; 1062 } 1063 value = strtol(token->text, &end, base); 1064 if (*end != 0) 1065 token_err(yylineno, infile, yytext, 1066 "illegal number conversion"); 1067 1068 /* 1069 * If this is a 64-bit value we need to store two literals 1070 * and issue a `lxjoin' to combine them. But that's a future 1071 * project. 1072 */ 1073 emit("b(lit)"); 1074 spit(value>>24); 1075 spit((value>>16)&0x0ff); 1076 spit((value>>8)&0x0ff); 1077 spit(value&0x0ff); 1078 } 1079 break; 1080 case TOK_C_LIT: 1081 STATE(token->text, "TOK_C_LIT"); 1082 emit("b(lit)"); 1083 spit(0); 1084 spit(0); 1085 spit(0); 1086 spit(token->text[1]); 1087 break; 1088 case TOK_STRING_LIT: 1089 STATE(token->text, "TOK_STRING_LIT:"); 1090 { 1091 int len; 1092 char *p = token->text; 1093 1094 ++p; /* Skip the quote */ 1095 len = strlen(++p); /* Skip the 1st space */ 1096 1097 #define ERR_TOOLONG \ 1098 token_err(yylineno, infile, yytext, "string length %d too long", len) 1099 1100 if (len > 255) 1101 ERR_TOOLONG; 1102 1103 if (p[len-1] == ')' || 1104 p[len-1] == '"') { 1105 p[len-1] = 0; 1106 } 1107 emit("b(\")"); 1108 sspit(p); 1109 } 1110 break; 1111 case TOK_PSTRING: 1112 STATE(token->text, "TOK_PSTRING:"); 1113 { 1114 int len; 1115 char *p = token->text; 1116 1117 if (*p++ == '.') p++; /* Skip over delimiter */ 1118 p++; /* Skip over space/tab */ 1119 1120 len = strlen(p); 1121 if (len > 255) 1122 ERR_TOOLONG; 1123 1124 if (p[len-1] == ')' || 1125 p[len-1] == '"') { 1126 p[len-1] = 0; 1127 } 1128 emit("b(\")"); 1129 sspit(p); 1130 emit("type"); 1131 } 1132 break; 1133 case TOK_TOKENIZE: 1134 STATE(token->text, "TOK_TOKENIZE"); 1135 /* The next pass should tokenize the FCODE number */ 1136 emit("b(')"); 1137 break; 1138 case TOK_COMMENT: 1139 STATE(token->text, "TOK_COMMENT:"); 1140 while (((token = yylex()) != NULL) && token->type != TOK_ENDCOMMENT) 1141 ; 1142 break; 1143 case TOK_ENDCOMMENT: 1144 STATE(token->text, "TOK_ENDCOMMENT"); 1145 token_err(yylineno, infile, NULL, 1146 "ENDCOMMENT encountered outside comment"); 1147 break; 1148 case TOK_COLON: 1149 STATE(token->text, "TOK_COLON:"); 1150 1151 token = yylex(); 1152 if (token == NULL) 1153 token_err(yylineno, infile, yytext, 1154 "EOF in colon definition"); 1155 1156 /* Add new code to dictionary */ 1157 fcode = malloc(sizeof(*fcode)); 1158 if (fcode == NULL) 1159 (void)err(1, "out of memory"); 1160 1161 fcode->num = nextfcode++; 1162 fcode->name = strdup(token->text); 1163 if (fcode->name == NULL) 1164 (void)err(1, "out of memory"); 1165 1166 if (!fadd(dictionary, fcode)) 1167 token_err(yylineno, infile, NULL, 1168 "Duplicate definition: `%s'\n", fcode->name); 1169 #ifdef DEBUG 1170 if (debug) 1171 (void)printf("Adding %s to dictionary\n", token->text); 1172 #endif 1173 if (state == 0) 1174 emit("new-token"); 1175 else { 1176 if (state == TOK_EXTERNAL) 1177 emit("external-token"); 1178 else 1179 /* Here we have a choice of new-token or named-token */ 1180 emit("named-token"); 1181 sspit(token->text); 1182 } 1183 spit(fcode->num); 1184 emit("b(:)"); 1185 last_token = fcode->name; 1186 defining = 1; 1187 break; 1188 case TOK_SEMICOLON: 1189 STATE(token->text, "TOK_SEMICOLON:"); 1190 emit("b(;)"); 1191 defining = 0; 1192 if (depth()) { 1193 token_err(yylineno, infile, NULL, 1194 "Warning: stack depth %d at end of %s\n", 1195 depth(), last_token); 1196 } 1197 last_token = ""; 1198 break; 1199 1200 /* These are special */ 1201 case TOK_AGAIN: 1202 STATE(token->text, "TOK_AGAIN"); 1203 emit("bbranch"); 1204 pos = pop(); 1205 pos -= outpos; 1206 if (offsetsize == 16) { 1207 spit((pos>>8)&0xff); 1208 } 1209 spit(pos&0xff); 1210 break; 1211 case TOK_ALIAS: 1212 STATE(token->text, "TOK_ALIAS"); 1213 { 1214 struct macro *alias; 1215 1216 token = yylex(); 1217 if (token == NULL) { 1218 (void)printf( "EOF in alias definition\n"); 1219 return; 1220 } 1221 if (token->type != TOK_OTHER) { 1222 (void)printf( "ENDCOMMENT aliasing weird token type %d\n", 1223 token->type); 1224 } 1225 alias = malloc(sizeof(*alias)); 1226 if (alias == NULL) 1227 (void)err(1, "out of memory"); 1228 1229 alias->name = strdup(token->text); 1230 if (alias->name == NULL) 1231 (void)err(1, "out of memory"); 1232 1233 token = yylex(); 1234 if (token == NULL) { 1235 free(alias); 1236 (void)printf( "EOF in alias definition\n"); 1237 return; 1238 } 1239 alias->equiv = strdup(token->text); 1240 if (alias->equiv == NULL) 1241 (void)err(1, "out of memory"); 1242 1243 if (!aadd(aliases, alias)) { 1244 (void)printf( "ERROR: Duplicate alias %s\n", 1245 alias->name); 1246 exit(1); 1247 } 1248 } 1249 break; 1250 case TOK_GETTOKEN: 1251 STATE(token->text, "TOK_GETTOKEN"); 1252 /* This is caused by ['] */ 1253 emit("b(')"); 1254 token = yylex(); 1255 if (token == NULL) { 1256 (void)printf( "EOF in [']\n"); 1257 return; 1258 } 1259 if ((fcode = flookup(dictionary, token->text)) == NULL) { 1260 (void)printf( "[']: %s not found\n", token->text); 1261 exit(1); 1262 } 1263 spit(fcode->num); 1264 break; 1265 case TOK_ASCII: 1266 STATE(token->text, "TOK_ASCII"); 1267 token = yylex(); 1268 if (token == NULL) { 1269 (void)printf( "EOF after \"ascii\"\n"); 1270 exit(1); 1271 } 1272 emit("b(lit)"); 1273 spit(0); 1274 spit(0); 1275 spit(0); 1276 spit(token->text[0]); 1277 break; 1278 case TOK_BEGIN: 1279 STATE(token->text, "TOK_BEGIN"); 1280 emit("b(<mark)"); 1281 push(outpos); 1282 break; 1283 case TOK_BUFFER: 1284 STATE(token->text, "TOK_BUFFER"); 1285 1286 token = yylex(); 1287 if (token == NULL) { 1288 (void)printf( "EOF in colon definition\n"); 1289 return; 1290 } 1291 1292 /* Add new code to dictionary */ 1293 fcode = malloc(sizeof(*fcode)); 1294 if (fcode == NULL) 1295 (void)err(1, "out of memory"); 1296 1297 fcode->num = nextfcode++; 1298 fcode->name = strdup(token->text); 1299 if (fcode->name == NULL) 1300 (void)err(1, "out of memory"); 1301 1302 fadd(dictionary, fcode); 1303 1304 if (state == 0) 1305 emit("new-token"); 1306 else { 1307 if (state == TOK_EXTERNAL) 1308 emit("external-token"); 1309 else 1310 /* Here we have a choice of new-token or named-token */ 1311 emit("named-token"); 1312 sspit(token->text); 1313 } 1314 spit(fcode->num); 1315 emit("b(buffer:)"); 1316 break; 1317 case TOK_CASE: 1318 STATE(token->text, "TOK_CASE"); 1319 emit("b(case)"); 1320 push(0); 1321 break; 1322 case TOK_CONSTANT: 1323 STATE(token->text, "TOK_CONSTANT"); 1324 1325 token = yylex(); 1326 if (token == NULL) { 1327 (void)printf( "EOF in constant definition\n"); 1328 return; 1329 } 1330 1331 /* Add new code to dictionary */ 1332 fcode = malloc(sizeof(*fcode)); 1333 if (fcode == NULL) 1334 (void)err(1, "out of memory"); 1335 fcode->num = nextfcode++; 1336 fcode->name = strdup(token->text); 1337 if (fcode->name == NULL) 1338 (void)err(1, "out of memory"); 1339 1340 fadd(dictionary, fcode); 1341 1342 if (state == 0) 1343 emit("new-token"); 1344 else { 1345 if (state == TOK_EXTERNAL) 1346 emit("external-token"); 1347 else 1348 /* Here we have a choice of new-token or named-token */ 1349 emit("named-token"); 1350 sspit(token->text); 1351 } 1352 spit(fcode->num); 1353 emit("b(constant)"); 1354 break; 1355 case TOK_CONTROL: 1356 STATE(token->text, "TOK_CONTROL"); 1357 token = yylex(); 1358 if (token == NULL) { 1359 (void)printf( "EOF after \"ascii\"\n"); 1360 exit(1); 1361 } 1362 emit("b(lit)"); 1363 spit(0); 1364 spit(0); 1365 spit(0); 1366 spit(token->text[0]&0x1f); 1367 break; 1368 case TOK_CREATE: 1369 STATE(token->text, "TOK_CREATE"); 1370 /* Don't know what this does or if it's right */ 1371 token = yylex(); 1372 if (token == NULL) { 1373 (void)printf( "EOF in create definition\n"); 1374 return; 1375 } 1376 1377 /* Add new code to dictionary */ 1378 fcode = malloc(sizeof(*fcode)); 1379 if (fcode == NULL) 1380 err(1, "out of memory"); 1381 1382 fcode->num = nextfcode++; 1383 fcode->name = strdup(token->text); 1384 if (fcode->name == NULL) 1385 (void)err(1, "out of memory"); 1386 1387 fadd(dictionary, fcode); 1388 1389 if (state == 0) 1390 emit("new-token"); 1391 else { 1392 if (state == TOK_EXTERNAL) 1393 emit("external-token"); 1394 else 1395 /* Here we have a choice of new-token or named-token */ 1396 emit("named-token"); 1397 sspit(token->text); 1398 } 1399 spit(fcode->num); 1400 emit("b(create)"); 1401 break; 1402 case TOK_DECIMAL: 1403 STATE(token->text, "TOK_DECIMAL"); 1404 if (token->text[1] != '#') { 1405 if (defining) { 1406 spit(10); 1407 emit("base"); 1408 emit("!"); 1409 } else 1410 base = TOK_DECIMAL; 1411 } else { 1412 char *end; 1413 Cell value; 1414 1415 token = yylex(); 1416 if (token == NULL) { 1417 (void)printf( "EOF after d#\n"); 1418 return; 1419 } 1420 if (token->type == TOK_OTHER) { 1421 if (strcmp("-1", token->text) == 0) { 1422 emit(token->text); 1423 break; 1424 } 1425 } 1426 value = strtol(token->text, &end, 10); 1427 if (*end != 0) 1428 token_err(yylineno, infile, NULL, 1429 "Illegal number conversion: %s", token->text); 1430 1431 /* 1432 * If this is a 64-bit value we need to store two literals 1433 * and issue a `lxjoin' to combine them. But that's a future 1434 * project. 1435 */ 1436 emit("b(lit)"); 1437 spit(value>>24); 1438 spit((value>>16)&0x0ff); 1439 spit((value>>8)&0x0ff); 1440 spit(value&0x0ff); 1441 } 1442 break; 1443 case TOK_DEFER: 1444 STATE(token->text, "TOK_DEFER"); 1445 /* Don't know what this does or if it's right */ 1446 token = yylex(); 1447 if (token == NULL) { 1448 (void)printf( "EOF in colon definition\n"); 1449 return; 1450 } 1451 1452 /* Add new code to dictionary */ 1453 fcode = malloc(sizeof(*fcode)); 1454 if (fcode == NULL) 1455 (void)err(1, "out of memory"); 1456 1457 fcode->num = nextfcode++; 1458 fcode->name = strdup(token->text); 1459 if (fcode->name == NULL) 1460 (void)err(1, "out of memory"); 1461 1462 fadd(dictionary, fcode); 1463 1464 if (state == 0) 1465 emit("new-token"); 1466 else { 1467 if (state == TOK_EXTERNAL) 1468 emit("external-token"); 1469 else 1470 /* Here we have a choice of new-token or named-token */ 1471 emit("named-token"); 1472 sspit(token->text); 1473 } 1474 spit(fcode->num); 1475 emit("b(defer)"); 1476 break; 1477 case TOK_DO: 1478 STATE(token->text, "TOK_DO"); 1479 /* 1480 * From the 1275 spec. B is branch location, T is branch target. 1481 * 1482 * b(do) offset1 ... b(loop) offset2 ... 1483 * b(do) offset1 ... b(+loop) offset2 ... 1484 * b(?do) offset1 ... b(loop) offset2 ... 1485 * b(?do) offset1 ... b(+loop) offset2 ... 1486 * ^ ^ 1487 * B1 ^ ^ T1 1488 * T2 B2 1489 * 1490 * How we do this is we generate the b(do) or b(?do), spit out a 1491 * zero offset while remembering b1 and t2. Then we call tokenize() 1492 * to generate the body. When tokenize() finds a b(loop) or b(+loop), 1493 * it generates the FCode and returns, with outpos at b2. We then 1494 * calculate the offsets, put them in the right slots and finishup. 1495 */ 1496 1497 if (token->text[0] == '?') 1498 emit("b(?do)"); 1499 else 1500 emit("b(do)"); 1501 push(outpos); 1502 if (offsetsize == 16) { 1503 spit(0); 1504 } 1505 spit(0); /* Place holder for later */ 1506 push(outpos); 1507 break; 1508 case TOK_ELSE: 1509 STATE(token->text, "TOK_ELSE"); 1510 /* Get where we need to patch */ 1511 off = pop(); 1512 emit("bbranch"); 1513 /* Save where we are now. */ 1514 push(outpos); 1515 if (offsetsize == 16) { 1516 spit(0); /* Place holder for later */ 1517 } 1518 spit(0); /* Place holder for later */ 1519 emit("b(>resolve)"); 1520 /* Rewind and patch the if branch */ 1521 pos = outpos; 1522 outpos = off; 1523 off = pos - off; 1524 if (offsetsize == 16) { 1525 spit(0); /* Place holder for later */ 1526 } 1527 spit(0); /* Place holder for later */ 1528 /* revert to the end */ 1529 outpos = pos; 1530 break; 1531 case TOK_ENDCASE: 1532 STATE(token->text, "TOK_ENDCASE:"); 1533 pos = outpos; /* Remember where we need to branch to */ 1534 1535 /* Thread our way backwards and install proper offsets */ 1536 off = pop(); 1537 while (off) { 1538 int tmp; 1539 1540 /* Move to this offset */ 1541 outpos = off; 1542 /* Load next offset to process */ 1543 tmp = outbuf[outpos]; 1544 1545 /* process this offset */ 1546 off = pos - outpos; 1547 if (offsetsize == 16) { 1548 spit((off>>8)&0xff); 1549 } 1550 spit(off&0xff); 1551 off = tmp; 1552 } 1553 outpos = pos; 1554 emit("b(endcase)"); 1555 break; 1556 case TOK_ENDOF: 1557 STATE(token->text, "TOK_ENDOF"); 1558 off = pop(); 1559 emit("b(endof)"); 1560 /* 1561 * Save back pointer in the offset field so we can traverse 1562 * the linked list and patch it in the endcase. 1563 */ 1564 pos = pop(); /* get position of prev link. */ 1565 push(outpos); /* save position of this link. */ 1566 spit(pos); /* save position of prev link. */ 1567 if (offsetsize == 16) { 1568 spit(0); 1569 } 1570 pos = outpos; 1571 /* Now point the offset from b(of) here. */ 1572 outpos = off; 1573 off = outpos - off; 1574 if (offsetsize == 16) { 1575 spit((off>>8)&0xff); 1576 } 1577 spit(off&0xff); 1578 /* Restore position */ 1579 outpos = pos; 1580 break; 1581 case TOK_EXTERNAL: 1582 STATE(token->text, "TOK_EXTERNAL"); 1583 state = TOK_EXTERNAL; 1584 break; 1585 case TOK_FIELD: 1586 STATE(token->text, "TOK_FIELD"); 1587 1588 token = yylex(); 1589 if (token == NULL) { 1590 (void)printf( "EOF in field definition\n"); 1591 return; 1592 } 1593 1594 /* Add new code to dictionary */ 1595 fcode = malloc(sizeof(*fcode)); 1596 if (fcode == NULL) 1597 (void)err(1, "out of memory"); 1598 1599 fcode->num = nextfcode++; 1600 fcode->name = strdup(token->text); 1601 if (fcode->name == NULL) 1602 (void)err(1, "out of memory"); 1603 1604 fadd(dictionary, fcode); 1605 1606 if (state == 0) 1607 emit("new-token"); 1608 else { 1609 if (state == TOK_EXTERNAL) 1610 emit("external-token"); 1611 else 1612 /* Here we have a choice of new-token or named-token */ 1613 emit("named-token"); 1614 sspit(token->text); 1615 } 1616 spit(fcode->num); 1617 emit("b(field)"); 1618 break; 1619 1620 case TOK_HEX: 1621 STATE(token->text, "TOK_HEX"); 1622 if (token->text[1] != '#') { 1623 if (defining) { 1624 spit(16); 1625 emit("base"); 1626 emit("!"); 1627 } else 1628 base = TOK_HEX; 1629 } else { 1630 char *end; 1631 Cell value; 1632 1633 token = yylex(); 1634 if (token == NULL) { 1635 (void)printf( "EOF after h#\n"); 1636 return; 1637 } 1638 value = strtol(token->text, &end, 16); 1639 if (*end != 0) { 1640 (void)printf("Illegal number conversion:%s:%d: %s\n", 1641 infile, yylineno, yytext); 1642 exit(1); 1643 } 1644 /* 1645 * If this is a 64-bit value we need to store two literals 1646 * and issue a `lxjoin' to combine them. But that's a future 1647 * project. 1648 */ 1649 emit("b(lit)"); 1650 spit(value>>24); 1651 spit((value>>16)&0x0ff); 1652 spit((value>>8)&0x0ff); 1653 spit(value&0x0ff); 1654 } 1655 break; 1656 case TOK_HEADERLESS: 1657 STATE(token->text, "TOK_HEADERLESS"); 1658 state = 0; 1659 break; 1660 case TOK_HEADERS: 1661 STATE(token->text, "TOK_HEADERS"); 1662 state = TOK_HEADERS; 1663 break; 1664 case TOK_OFFSET16: 1665 STATE(token->text, "TOK_OFFSET16"); 1666 offsetsize = 16; 1667 emit("offset16"); 1668 break; 1669 case TOK_IF: 1670 STATE(token->text, "TOK_IF"); 1671 /* 1672 * Similar to do but simpler since we only deal w/one branch. 1673 */ 1674 emit("b?branch"); 1675 push(outpos); 1676 if (offsetsize == 16) { 1677 spit(0); /* Place holder for later */ 1678 } 1679 spit(0); /* Place holder for later */ 1680 break; 1681 case TOK_LEAVE: 1682 STATE(token->text, "TOK_LEAVE"); 1683 emit("b(leave)"); 1684 break; 1685 case TOK_LOOP: 1686 STATE(token->text, "TOK_LOOP"); 1687 1688 if (token->text[0] == '+') 1689 emit("b(+loop)"); 1690 else 1691 emit("b(loop)"); 1692 /* First do backwards branch of loop */ 1693 pos = pop(); 1694 off = pos - outpos; 1695 if (offsetsize == 16) { 1696 spit((off>>8)&0xff); 1697 } 1698 spit(off&0xff); 1699 /* Now do forward branch of do */ 1700 pos = outpos; 1701 outpos = pop(); 1702 off = pos - outpos; 1703 if (offsetsize == 16) { 1704 spit((off>>8)&0xff); 1705 } 1706 spit(off&0xff); 1707 /* Restore output position */ 1708 outpos = pos; 1709 break; 1710 case TOK_OCTAL: 1711 STATE(token->text, "TOK_OCTAL"); 1712 if (token->text[1] != '#') { 1713 if (defining) { 1714 spit(16); 1715 emit("base"); 1716 emit("!"); 1717 } else 1718 base = TOK_OCTAL; 1719 } else { 1720 char *end; 1721 Cell value; 1722 1723 token = yylex(); 1724 if (token == NULL) { 1725 (void)printf( "EOF after o#\n"); 1726 return; 1727 } 1728 value = strtol(token->text, &end, 8); 1729 if (*end != 0) { 1730 (void)printf("Illegal number conversion:%s:%d: %s\n", 1731 infile, yylineno, yytext); 1732 exit(1); 1733 } 1734 /* 1735 * If this is a 64-bit value we need to store two literals 1736 * and issue a `lxjoin' to combine them. But that's a future 1737 * project. 1738 */ 1739 emit("b(lit)"); 1740 spit(value>>24); 1741 spit((value>>16)&0x0ff); 1742 spit((value>>8)&0x0ff); 1743 spit(value&0x0ff); 1744 } 1745 break; 1746 case TOK_OF: 1747 STATE(token->text, "TOK_OF"); 1748 /* 1749 * Let's hope I get the semantics right. 1750 * 1751 * The `of' behaves almost the same as an 1752 * `if'. The difference is that `endof' 1753 * takes a branch offset to the associated 1754 * `endcase'. Here we will generate a temporary 1755 * offset of the `of' associated with the `endof'. 1756 * Then in `endcase' we should be pointing just 1757 * after the offset of the last `endof' so we 1758 * calculate the offset and thread our way backwards 1759 * searching for the previous `b(case)' or `b(endof)'. 1760 */ 1761 emit("b(of)"); 1762 push(outpos); 1763 if (offsetsize == 16) { 1764 spit(0); 1765 } 1766 spit(0); /* Place holder for later */ 1767 break; 1768 case TOK_REPEAT: 1769 STATE(token->text, "TOK_REPEAT"); 1770 emit("bbranch"); 1771 pos = pop(); 1772 off = pop(); 1773 /* First the offset for the branch back to the begin */ 1774 off -= outpos; 1775 if (offsetsize == 16) { 1776 spit((off>>8)&0xff); 1777 } 1778 spit(off&0xff); 1779 emit("b(>resolve)"); 1780 /* Now point the offset of the while here. */ 1781 off = outpos; 1782 outpos = pos; 1783 pos = off - pos; 1784 if (offsetsize == 16) { 1785 spit((pos>>8)&0xff); 1786 } 1787 spit(pos&0xff); 1788 /* Return to the end of the output */ 1789 outpos = off; 1790 break; 1791 case TOK_THEN: 1792 STATE(token->text, "TOK_THEN"); 1793 emit("b(>resolve)"); 1794 pos = outpos; 1795 outpos = pop(); 1796 off = pos - outpos; 1797 if (offsetsize == 16) { 1798 spit((off>>8)&0xff); 1799 } 1800 spit(off&0xff); 1801 outpos = pos; 1802 break; 1803 case TOK_TO: 1804 STATE(token->text, "TOK_TO"); 1805 /* The next pass should tokenize the FCODE number */ 1806 emit("b(to)"); 1807 break; 1808 case TOK_UNTIL: 1809 STATE(token->text, "TOK_UNTIL"); 1810 { 1811 int pos; 1812 1813 emit("b?branch"); 1814 pos = pop(); 1815 pos -= outpos; 1816 if (offsetsize == 16) { 1817 spit((pos>>8)&0xff); 1818 } 1819 spit(pos&0xff); 1820 } 1821 break; 1822 case TOK_VALUE: 1823 STATE(token->text, "TOK_VALUE"); 1824 1825 token = yylex(); 1826 if (token == NULL) { 1827 (void)printf( "EOF in value definition\n"); 1828 return; 1829 } 1830 1831 /* Add new code to dictionary */ 1832 fcode = malloc(sizeof(*fcode)); 1833 if (fcode == NULL) 1834 (void)err(1, "out of memory"); 1835 1836 fcode->num = nextfcode++; 1837 fcode->name = strdup(token->text); 1838 if (fcode->name == NULL) 1839 (void)err(1, "out of memory"); 1840 1841 fadd(dictionary, fcode); 1842 1843 if (state == 0) 1844 emit("new-token"); 1845 else { 1846 if (state == TOK_EXTERNAL) 1847 emit("external-token"); 1848 else 1849 /* Here we have a choice of new-token or named-token */ 1850 emit("named-token"); 1851 sspit(token->text); 1852 } 1853 spit(fcode->num); 1854 emit("b(value)"); 1855 break; 1856 case TOK_VARIABLE: 1857 STATE(token->text, "TOK_VARIABLE"); 1858 1859 token = yylex(); 1860 if (token == NULL) { 1861 (void)printf( "EOF in variable definition\n"); 1862 return; 1863 } 1864 1865 /* Add new code to dictionary */ 1866 fcode = malloc(sizeof(*fcode)); 1867 if (fcode == NULL) 1868 (void)err(1, "out of memory"); 1869 1870 fcode->num = nextfcode++; 1871 fcode->name = strdup(token->text); 1872 if (fcode->name == NULL) 1873 (void)err(1, "out of memory"); 1874 1875 fadd(dictionary, fcode); 1876 1877 if (state == 0) 1878 emit("new-token"); 1879 else { 1880 if (state == TOK_EXTERNAL) 1881 emit("external-token"); 1882 else 1883 /* Here we have a choice of new-token or named-token */ 1884 emit("named-token"); 1885 sspit(token->text); 1886 } 1887 spit(fcode->num); 1888 emit("b(variable)"); 1889 break; 1890 case TOK_WHILE: 1891 STATE(token->text, "TOK_WHILE"); 1892 emit("b?branch"); 1893 push(outpos); 1894 if (offsetsize == 16) { 1895 spit(0); 1896 } 1897 spit(0); 1898 break; 1899 1900 /* Tokenizer directives */ 1901 case TOK_BEGTOK: 1902 STATE(token->text, "TOK_BEGTOK"); 1903 tokenizer = 1; 1904 break; 1905 case TOK_EMIT_BYTE: 1906 STATE(token->text, "TOK_EMIT_BYTE"); 1907 spit(pop()); 1908 break; 1909 case TOK_ENDTOK: 1910 STATE(token->text, "TOK_ENDTOK"); 1911 tokenizer = 0; 1912 break; 1913 case TOK_FLOAD: 1914 STATE(token->text, "TOK_FLOAD"); 1915 /* Parse a different file for a while */ 1916 token = yylex(); 1917 if ((inf = fopen(token->text, "r")) == NULL) { 1918 (void)printf("%s: Could not open %s: %s\n", 1919 myname, token->text, strerror(errno)); 1920 break; 1921 } 1922 inbuf = yy_create_buffer(inf, YY_BUF_SIZE); 1923 yy_switch_to_buffer(inbuf); 1924 { 1925 char *oldinfile = infile; 1926 1927 infile = token->text; 1928 tokenize(inbuf); 1929 infile = oldinfile; 1930 } 1931 yy_switch_to_buffer(input); 1932 yy_delete_buffer(inbuf); 1933 fclose(inf); 1934 break; 1935 case TOK_OTHER: 1936 STATE(token->text, "TOK_OTHER"); 1937 if (apply_macros(input, token->text)) 1938 break; 1939 if (emit(token->text)) { 1940 #if 0 1941 /* 1942 * Call an external command 1943 * 1944 * XXXXX assumes it will always find the command 1945 */ 1946 sspit(token->text); 1947 emit("$find"); 1948 emit("drop"); 1949 emit("execute"); 1950 #else 1951 (void)printf( "%s: undefined token `%s'\n", 1952 myname, token->text); 1953 fflush(stderr); 1954 exit(1); 1955 #endif 1956 } 1957 break; 1958 default: 1959 break; 1960 } 1961 } 1962 return; 1963 } 1964 1965 /* 1966 * print a tokenizer error message 1967 */ 1968 void 1969 token_err(int lineno, char *infile, char *text, char *fmt, ...) 1970 { 1971 va_list ap; 1972 1973 va_start(ap, fmt); 1974 if (infile) 1975 (void)fprintf(stderr, "%s:%d: ", infile, lineno); 1976 if (fmt) 1977 (void)vfprintf(stderr, fmt, ap); 1978 fputc('\n', stderr); 1979 if (text) 1980 fprintf(stderr, "\t%s", text); 1981 va_end(ap); 1982 exit(1); 1983 } 1984 1985 /* 1986 * Lookup fcode string in dictionary and spit it out. 1987 * 1988 * Fcode must be in dictionary. No alias conversion done. 1989 */ 1990 int 1991 emit(str) 1992 char *str; 1993 { 1994 struct fcode *code; 1995 if ((code = flookup( dictionary, str))) 1996 spit(code->num); 1997 #ifdef DEBUG 1998 if (debug > 1) { 1999 if (code) 2000 (void)printf( "emitting `%s'\n", code->name); 2001 else 2002 (void)printf( "emit: not found `%s'\n", str); 2003 } 2004 #endif 2005 return (code == NULL); 2006 } 2007 2008 /* 2009 * Spit out an integral value as a series of FCodes. 2010 * 2011 * It will spit out one zero byte or as many bytes as are 2012 * non-zero. 2013 */ 2014 int 2015 spit(n) 2016 long n; 2017 { 2018 int count = 1; 2019 2020 if (n >> 8) 2021 count += spit(n >> 8); 2022 if (outpos >= outbufsiz) { 2023 while (outpos >= outbufsiz) outbufsiz += BUFCLICK; 2024 if (!(outbuf = realloc(outbuf, outbufsiz))) { 2025 (void)printf( "realloc of %ld bytes failed -- out of memory\n", 2026 (long)outbufsiz); 2027 exit(1); 2028 } 2029 } 2030 outbuf[outpos++] = n; 2031 return (count); 2032 } 2033 2034 /* 2035 * Spit out an FCode string. 2036 */ 2037 void 2038 sspit(s) 2039 char *s; 2040 { 2041 int len = strlen(s); 2042 2043 if (len > 255) { 2044 (void)printf( "string length %d too long\n", len); 2045 return; 2046 } 2047 #ifdef DEBUG 2048 if (debug > 1) 2049 (void)printf( "sspit: len %d str `%s'\n", len, s); 2050 #endif 2051 spit(len); 2052 while (*s) 2053 spit(*s++); 2054 } 2055 2056 int 2057 yywrap() 2058 { 2059 /* Always generate EOF */ 2060 return (1); 2061 } 2062