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