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 } 2066