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