|
|
1.1 ! root 1: /* tag: forth bootstrap environment ! 2: * ! 3: * Copyright (C) 2003-2006 Stefan Reinauer, Patrick Mauritz ! 4: * ! 5: * See the file "COPYING" for further information about ! 6: * the copyright and warranty status of this work. ! 7: */ ! 8: ! 9: #include "sysinclude.h" ! 10: #include <stdio.h> ! 11: #include <stdlib.h> ! 12: #include <string.h> ! 13: #include <signal.h> ! 14: #include <fcntl.h> ! 15: #include <unistd.h> ! 16: #include <termios.h> ! 17: #include <sys/stat.h> ! 18: ! 19: #ifdef __GLIBC__ ! 20: #define _GNU_SOURCE ! 21: #include <getopt.h> ! 22: #endif ! 23: ! 24: #include "config.h" ! 25: #include "kernel/stack.h" ! 26: #include "sysinclude.h" ! 27: #include "kernel/kernel.h" ! 28: #include "dict.h" ! 29: #include "cross.h" ! 30: #include "openbios-version.h" ! 31: ! 32: #define MAX_PATH_LEN 256 ! 33: ! 34: #define MEMORY_SIZE (1024*1024) /* 1M ram for hosted system */ ! 35: #define DICTIONARY_SIZE (256*1024) /* 256k for the dictionary */ ! 36: #define TRAMPOLINE_SIZE (4*sizeof(cell)) /* 4 cells for the trampoline */ ! 37: ! 38: /* state variables */ ! 39: static ucell *latest, *state, *base; ! 40: static ucell *memory; ! 41: ucell *trampoline; ! 42: ! 43: /* local variables */ ! 44: static int errors = 0; ! 45: static int segfault = 0; ! 46: static int verbose = 0; ! 47: ! 48: #define MAX_SRC_FILES 128 ! 49: ! 50: static FILE *srcfiles[MAX_SRC_FILES]; ! 51: static char *srcfilenames[MAX_SRC_FILES]; ! 52: static int srclines[MAX_SRC_FILES]; ! 53: static unsigned int cursrc = 0; ! 54: ! 55: static char *srcbasedict; ! 56: ! 57: /* console variables */ ! 58: static FILE *console; ! 59: ! 60: #ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH ! 61: unsigned long base_address; ! 62: #endif ! 63: ! 64: /* include path handling */ ! 65: typedef struct include_path include; ! 66: struct include_path { ! 67: const char *path; ! 68: include *next; ! 69: }; ! 70: ! 71: static include includes = { ".", NULL }; ! 72: static FILE *depfile; ! 73: ! 74: static ucell * relocation_address=NULL; ! 75: static int relocation_length=0; ! 76: ! 77: /* the word names are used to generate the prim words in the ! 78: * dictionary. This is done by the C written interpreter. ! 79: */ ! 80: static const char *wordnames[] = { ! 81: "(semis)", "", "(lit)", "", "", "", "", "(do)", "(?do)", "(loop)", ! 82: "(+loop)", "", "", "", "dup", "2dup", "?dup", "over", "2over", "pick", "drop", ! 83: "2drop", "nip", "roll", "rot", "-rot", "swap", "2swap", ">r", "r>", ! 84: "r@", "depth", "depth!", "rdepth", "rdepth!", "+", "-", "*", "u*", ! 85: "mu/mod", "abs", "negate", "max", "min", "lshift", "rshift", ">>a", ! 86: "and", "or", "xor", "invert", "d+", "d-", "m*", "um*", "@", "c@", ! 87: "w@", "l@", "!", "+!", "c!", "w!", "l!", "=", ">", "<", "u>", "u<", ! 88: "sp@", "move", "fill", "(emit)", "(key?)", "(key)", "execute", ! 89: "here", "here!", "dobranch", "do?branch", "unaligned-w@", ! 90: "unaligned-w!", "unaligned-l@", "unaligned-l!", "ioc@", "iow@", ! 91: "iol@", "ioc!", "iow!", "iol!", "i", "j", "call", "sys-debug", ! 92: "$include", "$encode-file", "(debug", "(debug-off)" ! 93: }; ! 94: ! 95: /* ! 96: * dictionary related functions. ! 97: */ ! 98: ! 99: /* ! 100: * Compare two dictionaries constructed at different addresses. When ! 101: * the cells don't match, a need for relocation is detected and the ! 102: * corresponding bit in reloc_table bitmap is set. ! 103: */ ! 104: static void relocation_table(unsigned char * dict_one, unsigned char *dict_two, int length) ! 105: { ! 106: ucell *d1=(ucell *)dict_one, *d2=(ucell *)dict_two; ! 107: ucell *reloc_table; ! 108: int pos, bit; ! 109: int l=(length+(sizeof(cell)-1))/sizeof(ucell), i; ! 110: ! 111: /* prepare relocation table */ ! 112: relocation_length=(length+BITS-1)/BITS; ! 113: reloc_table = malloc(relocation_length*sizeof(cell)); ! 114: memset(reloc_table,0,relocation_length*sizeof(cell)); ! 115: ! 116: for (i=0; i<l; i++) { ! 117: ! 118: pos=i/BITS; ! 119: bit=i&~(-BITS); ! 120: ! 121: if(d1[i]==d2[i]) { ! 122: reloc_table[pos] &= target_ucell(~((ucell)1ULL << bit)); ! 123: ! 124: // This check might bring false positives in data. ! 125: //if(d1[i] >= pointer2cell(dict_one) && ! 126: // d1[i] <= pointer2cell(dict_one+length)) ! 127: // printk("\nWARNING: inconsistent relocation (%x:%x)!\n", d1[i], d2[i]); ! 128: } else { ! 129: /* This is a pointer, it needs relocation, d2==dict */ ! 130: reloc_table[pos] |= target_ucell((ucell)1ULL << bit); ! 131: d2[i] = target_ucell(target_ucell(d2[i]) - pointer2cell(d2)); ! 132: } ! 133: } ! 134: ! 135: #ifdef CONFIG_DEBUG_DICTIONARY ! 136: printk("dict1 %lx dict2 %lx dict %lx\n",dict_one, dict_two, dict); ! 137: for (i=0; i< relocation_length ; i++) ! 138: printk("reloc %d %lx\n",i+1, reloc_table[i]); ! 139: #endif ! 140: relocation_address=reloc_table; ! 141: } ! 142: ! 143: static void write_dictionary(const char *filename) ! 144: { ! 145: FILE *f; ! 146: unsigned char *write_data, *walk_data; ! 147: int write_len; ! 148: dictionary_header_t *header; ! 149: u32 checksum=0; ! 150: ! 151: /* ! 152: * get memory for dictionary ! 153: */ ! 154: ! 155: write_len = sizeof(dictionary_header_t)+dicthead+relocation_length*sizeof(cell); ! 156: write_data = malloc(write_len); ! 157: if(!write_data) { ! 158: printk("panic: can't allocate memory for output dictionary (%d" ! 159: " bytes\n", write_len); ! 160: exit(1); ! 161: } ! 162: memset(write_data, 0, write_len); ! 163: ! 164: /* ! 165: * prepare dictionary header ! 166: */ ! 167: ! 168: header = (dictionary_header_t *)write_data; ! 169: *header = (dictionary_header_t){ ! 170: .signature = DICTID, ! 171: .version = 2, ! 172: .cellsize = sizeof(ucell), ! 173: #ifdef CONFIG_BIG_ENDIAN ! 174: .endianess = -1, ! 175: #else ! 176: .endianess = 0, ! 177: #endif ! 178: .checksum = 0, ! 179: .compression = 0, ! 180: .relocation = -1, ! 181: .length = target_ulong((uint32_t)dicthead), ! 182: .last = target_ucell((ucell)((unsigned long)last ! 183: - (unsigned long)dict)), ! 184: }; ! 185: ! 186: /* ! 187: * prepare dictionary data ! 188: */ ! 189: ! 190: walk_data=write_data+sizeof(dictionary_header_t); ! 191: memcpy (walk_data, dict, dicthead); ! 192: ! 193: /* ! 194: * prepare relocation data. ! 195: * relocation_address is zero when writing a dictionary core. ! 196: */ ! 197: ! 198: if (relocation_address) { ! 199: #ifdef CONFIG_DEBUG_DICTIONARY ! 200: printk("writing %d reloc cells \n",relocation_length); ! 201: #endif ! 202: walk_data += dicthead; ! 203: memcpy(walk_data, relocation_address, ! 204: relocation_length*sizeof(cell)); ! 205: /* free relocation information */ ! 206: free(relocation_address); ! 207: relocation_address=NULL; ! 208: } else { ! 209: header->relocation=0; ! 210: } ! 211: ! 212: /* ! 213: * Calculate Checksum ! 214: */ ! 215: ! 216: walk_data=write_data; ! 217: while (walk_data<write_data+write_len) { ! 218: checksum+=read_long(walk_data); ! 219: walk_data+=sizeof(u32); ! 220: } ! 221: checksum=(u32)-checksum; ! 222: ! 223: header->checksum=target_long(checksum); ! 224: ! 225: if (verbose) { ! 226: dump_header(header); ! 227: } ! 228: ! 229: f = fopen(filename, "w"); ! 230: if (!f) { ! 231: printk("panic: can't write to dictionary '%s'.\n", filename); ! 232: exit(1); ! 233: } ! 234: ! 235: fwrite(write_data, write_len, 1, f); ! 236: ! 237: free(write_data); ! 238: fclose(f); ! 239: ! 240: #ifdef CONFIG_DEBUG_DICTIONARY ! 241: printk("wrote dictionary to file %s.\n", filename); ! 242: #endif ! 243: } ! 244: ! 245: /* ! 246: * Write dictionary as a list of ucell hex values to filename. Array ! 247: * header and end lines are not generated. ! 248: * ! 249: * Cells with relocations are output using the expression ! 250: * DICTIONARY_BASE + value. ! 251: * ! 252: * Define some helpful constants. ! 253: */ ! 254: static void write_dictionary_hex(const char *filename) ! 255: { ! 256: FILE *f; ! 257: ucell *walk; ! 258: ! 259: f = fopen(filename, "w"); ! 260: if (!f) { ! 261: printk("panic: can't write to dictionary '%s'.\n", filename); ! 262: exit(1); ! 263: } ! 264: ! 265: for (walk = (ucell *)dict; walk < (ucell *)(dict + dicthead); walk++) { ! 266: int pos, bit, l; ! 267: ucell val; ! 268: ! 269: l = (walk - (ucell *)dict); ! 270: pos = l / BITS; ! 271: bit = l & ~(-BITS); ! 272: ! 273: val = read_ucell(walk); ! 274: if (relocation_address[pos] & target_ucell((ucell)1ULL << bit)) { ! 275: fprintf(f, "DICTIONARY_BASE + 0x%" FMT_CELL_x ! 276: ",\n", val); ! 277: } else { ! 278: fprintf(f, "0x%" FMT_CELL_x",\n", val); ! 279: } ! 280: } ! 281: ! 282: fprintf(f, "#define FORTH_DICTIONARY_LAST 0x%" FMT_CELL_x"\n", ! 283: (ucell)((unsigned long)last - (unsigned long)dict)); ! 284: fprintf(f, "#define FORTH_DICTIONARY_END 0x%" FMT_CELL_x"\n", ! 285: (ucell)dicthead); ! 286: fclose(f); ! 287: ! 288: #ifdef CONFIG_DEBUG_DICTIONARY ! 289: printk("wrote dictionary to file %s.\n", filename); ! 290: #endif ! 291: } ! 292: ! 293: static ucell read_dictionary(char *fil) ! 294: { ! 295: int ilen; ! 296: ucell ret; ! 297: char *mem; ! 298: FILE *f; ! 299: struct stat finfo; ! 300: ! 301: if (stat(fil, &finfo)) ! 302: return 0; ! 303: ! 304: ilen = finfo.st_size; ! 305: ! 306: if ((mem = malloc(ilen)) == NULL) { ! 307: printk("panic: not enough memory.\n"); ! 308: exit(1); ! 309: } ! 310: ! 311: f = fopen(fil, "r"); ! 312: if (!f) { ! 313: printk("panic: can't open dictionary.\n"); ! 314: exit(1); ! 315: } ! 316: ! 317: if (fread(mem, ilen, 1, f) != 1) { ! 318: printk("panic: can't read dictionary.\n"); ! 319: fclose(f); ! 320: exit(1); ! 321: } ! 322: fclose(f); ! 323: ! 324: ret = load_dictionary(mem, ilen); ! 325: ! 326: free(mem); ! 327: return ret; ! 328: } ! 329: ! 330: ! 331: /* ! 332: * C Parser related functions ! 333: */ ! 334: ! 335: /* ! 336: * skipws skips all whitespaces (space, tab, newline) from the input file ! 337: */ ! 338: ! 339: static void skipws(FILE * f) ! 340: { ! 341: int c; ! 342: while (!feof(f)) { ! 343: c = getc(f); ! 344: ! 345: if (c == ' ' || c == '\t') ! 346: continue; ! 347: ! 348: if (c == '\n') { ! 349: srclines[cursrc - 1]++; ! 350: continue; ! 351: } ! 352: ! 353: ungetc(c, f); ! 354: break; ! 355: } ! 356: } ! 357: ! 358: /* ! 359: * parse gets the next word from the input stream, delimited by ! 360: * delim. If delim is 0, any word delimiter will end the stream ! 361: * word delimiters are space, tab and newline. The resulting word ! 362: * will be put zero delimited to the char array line. ! 363: */ ! 364: ! 365: static int parse(FILE * f, char *line, char delim) ! 366: { ! 367: int cnt = 0, c = 0; ! 368: ! 369: while (!feof(f)) { ! 370: c = getc(f); ! 371: ! 372: if (delim && c == delim) ! 373: break; ! 374: ! 375: if ((!delim) && (c == ' ' || c == '\t' || c == '\n')) ! 376: break; ! 377: ! 378: line[cnt++] = c; ! 379: } ! 380: ! 381: /* Update current line number */ ! 382: if (c == '\n') { ! 383: srclines[cursrc - 1]++; ! 384: } ! 385: ! 386: line[cnt] = 0; ! 387: ! 388: return cnt; ! 389: } ! 390: ! 391: /* ! 392: * parse_word is a small helper that skips whitespaces before a word. ! 393: * it's behaviour is similar to the forth version parse-word. ! 394: */ ! 395: ! 396: static void parse_word(FILE * f, char *line) ! 397: { ! 398: skipws(f); ! 399: parse(f, line, 0); ! 400: } ! 401: ! 402: ! 403: static void writestring(const char *str) ! 404: { ! 405: unsigned int i; ! 406: for (i = 0; i < strlen(str); i++) { ! 407: dict[dicthead + i] = str[i]; ! 408: } ! 409: dicthead += i + 1; ! 410: dict[dicthead - 1] = (char) strlen(str) + 128; ! 411: } ! 412: ! 413: #define writebyte(value) {write_byte(dict+dicthead,value); dicthead++;} ! 414: #define writecell(value) {write_cell(dict+dicthead, value); dicthead+=sizeof(cell);} ! 415: ! 416: /* ! 417: * reveal a word, ie. make it visible. ! 418: */ ! 419: ! 420: static void reveal(void) ! 421: { ! 422: *last = *latest; ! 423: } ! 424: ! 425: /* ! 426: * dictionary padding ! 427: */ ! 428: ! 429: static void paddict(ucell align) ! 430: { ! 431: while (dicthead % align != 0) ! 432: writebyte(0); ! 433: } ! 434: ! 435: /* ! 436: * generic forth word creator function. ! 437: */ ! 438: ! 439: static void fcreate(const char *word, ucell cfaval) ! 440: { ! 441: if (strlen(word) == 0) { ! 442: printk("WARNING: tried to create unnamed word.\n"); ! 443: return; ! 444: } ! 445: ! 446: writestring(word); ! 447: /* get us at least 1 byte for flags */ ! 448: writebyte(0); ! 449: paddict(sizeof(cell)); ! 450: /* set flags high bit. */ ! 451: dict[dicthead - 1] = 128; ! 452: /* lfa and cfa */ ! 453: writecell(read_ucell(latest)); ! 454: *latest = target_ucell(pointer2cell(dict) + dicthead - sizeof(cell)); ! 455: writecell(cfaval); ! 456: } ! 457: ! 458: ! 459: static ucell *buildvariable(const char *name, cell defval) ! 460: { ! 461: fcreate(name, DOVAR); /* see dict.h for DOVAR and other CFA ids */ ! 462: writecell(defval); ! 463: return (ucell *) (dict + dicthead - sizeof(cell)); ! 464: } ! 465: ! 466: static void buildconstant(const char *name, cell defval) ! 467: { ! 468: fcreate(name, DOCON); /* see dict.h for DOCON and other CFA ids */ ! 469: writecell(defval); ! 470: } ! 471: ! 472: static void builddefer(const char *name) ! 473: { ! 474: fcreate(name, DODFR); /* see dict.h for DODFR and other CFA ids */ ! 475: writecell((ucell)0); ! 476: writecell((ucell)findword("(semis)")); ! 477: } ! 478: ! 479: /* ! 480: * Include file handling ! 481: */ ! 482: ! 483: static void add_includepath(char *path) ! 484: { ! 485: include *incl = &includes; ! 486: include *newpath; ! 487: ! 488: while (incl->next) ! 489: incl = incl->next; ! 490: ! 491: newpath = malloc(sizeof(include)); ! 492: if (!newpath) { ! 493: printk("panic: not enough memory for include path.\n"); ! 494: exit(1); ! 495: } ! 496: ! 497: incl->next = newpath; ! 498: newpath->path = path; ! 499: newpath->next = NULL; ! 500: } ! 501: ! 502: ! 503: static FILE *fopen_include(const char *fil) ! 504: { ! 505: char fullpath[MAX_PATH_LEN]; ! 506: FILE *ret; ! 507: include *incl = &includes; ! 508: ! 509: while (incl) { ! 510: snprintf(fullpath, sizeof(fullpath), "%s/%s", incl->path, fil); ! 511: ! 512: ret = fopen(fullpath, "r"); ! 513: if (ret != NULL) { ! 514: ! 515: #ifdef CONFIG_DEBUG_INTERPRETER ! 516: printk("Including '%s'\n", name ); ! 517: #endif ! 518: srcfilenames[cursrc] = strdup(fil); ! 519: srclines [ cursrc ] = 1; ! 520: srcfiles [ cursrc++ ] = ret; ! 521: ! 522: if (depfile) { ! 523: fprintf(depfile, " %s", fullpath); ! 524: } ! 525: ! 526: return ret; ! 527: } ! 528: ! 529: incl = incl->next; ! 530: } ! 531: return NULL; ! 532: } ! 533: ! 534: ! 535: /* ! 536: * Forth exception handler ! 537: */ ! 538: ! 539: void exception(cell no) ! 540: { ! 541: printk("%s:%d: ", srcfilenames[cursrc - 1], srclines[cursrc - 1]); ! 542: ! 543: /* See also forth/bootstrap/interpreter.fs */ ! 544: switch (no) { ! 545: case -1: ! 546: case -2: ! 547: printk("Aborted.\n"); ! 548: break; ! 549: case -3: ! 550: printk("Stack Overflow.\n"); ! 551: break; ! 552: case -4: ! 553: printk("Stack Underflow.\n"); ! 554: break; ! 555: case -5: ! 556: printk("Return Stack Overflow.\n"); ! 557: break; ! 558: case -6: ! 559: printk("Return Stack Underflow.\n"); ! 560: break; ! 561: case -19: ! 562: printk("undefined word.\n"); ! 563: break; ! 564: case -21: ! 565: printk("out of memory.\n"); ! 566: break; ! 567: case -33: ! 568: printk("undefined method.\n"); ! 569: break; ! 570: case -34: ! 571: printk("no such device.\n"); ! 572: break; ! 573: default: ! 574: printk("error %" FMT_CELL_d " occured.\n", no); ! 575: } ! 576: exit(1); ! 577: } ! 578: ! 579: ! 580: /* ! 581: * This is the C version of the forth interpreter ! 582: */ ! 583: ! 584: static int interpret_source(char *fil) ! 585: { ! 586: FILE *f; ! 587: char tib[160]; ! 588: cell num; ! 589: char *test; ! 590: ! 591: const ucell SEMIS = (ucell)findword("(semis)"); ! 592: const ucell LIT = (ucell)findword("(lit)"); ! 593: const ucell DOBRANCH = (ucell)findword("dobranch"); ! 594: ! 595: if ((f = fopen_include(fil)) == NULL) { ! 596: printk("error while loading source file '%s'\n", fil); ! 597: errors++; ! 598: exit(1); ! 599: } ! 600: ! 601: /* FIXME: We should read this file at ! 602: * once. No need to get it char by char ! 603: */ ! 604: ! 605: while (!feof(f)) { ! 606: xt_t res; ! 607: parse_word(f, tib); ! 608: ! 609: /* if there is actually no word, we continue right away */ ! 610: if (strlen(tib) == 0) { ! 611: continue; ! 612: } ! 613: ! 614: /* Checking for builtin words that are needed to ! 615: * bootstrap the forth base dictionary. ! 616: */ ! 617: ! 618: if (!strcmp(tib, "(")) { ! 619: parse(f, tib, ')'); ! 620: continue; ! 621: } ! 622: ! 623: if (!strcmp(tib, "\\")) { ! 624: parse(f, tib, '\n'); ! 625: continue; ! 626: } ! 627: ! 628: if (!strcmp(tib, ":")) { ! 629: parse_word(f, tib); ! 630: ! 631: #ifdef CONFIG_DEBUG_INTERPRETER ! 632: printk("create colon word %s\n\n", tib); ! 633: #endif ! 634: fcreate(tib, DOCOL); /* see dict.h for DOCOL and other CFA ids */ ! 635: *state = (ucell) (-1); ! 636: continue; ! 637: } ! 638: ! 639: if (!strcmp(tib, ";")) { ! 640: #ifdef CONFIG_DEBUG_INTERPRETER ! 641: printk("finish colon definition\n\n"); ! 642: #endif ! 643: writecell((cell)SEMIS); ! 644: *state = (ucell) 0; ! 645: reveal(); ! 646: continue; ! 647: } ! 648: ! 649: if (!strcasecmp(tib, "variable")) { ! 650: parse_word(f, tib); ! 651: #ifdef CONFIG_DEBUG_INTERPRETER ! 652: printk("defining variable %s\n\n", tib); ! 653: #endif ! 654: buildvariable(tib, 0); ! 655: reveal(); ! 656: continue; ! 657: } ! 658: ! 659: if (!strcasecmp(tib, "constant")) { ! 660: parse_word(f, tib); ! 661: #ifdef CONFIG_DEBUG_INTERPRETER ! 662: printk("defining constant %s\n\n", tib); ! 663: #endif ! 664: buildconstant(tib, POP()); ! 665: reveal(); ! 666: continue; ! 667: } ! 668: ! 669: if (!strcasecmp(tib, "value")) { ! 670: parse_word(f, tib); ! 671: #ifdef CONFIG_DEBUG_INTERPRETER ! 672: printk("defining value %s\n\n", tib); ! 673: #endif ! 674: buildconstant(tib, POP()); ! 675: reveal(); ! 676: continue; ! 677: } ! 678: ! 679: if (!strcasecmp(tib, "defer")) { ! 680: parse_word(f, tib); ! 681: #ifdef CONFIG_DEBUG_INTERPRETER ! 682: printk("defining defer word %s\n\n", tib); ! 683: #endif ! 684: builddefer(tib); ! 685: reveal(); ! 686: continue; ! 687: } ! 688: ! 689: if (!strcasecmp(tib, "include")) { ! 690: parse_word(f, tib); ! 691: #ifdef CONFIG_DEBUG_INTERPRETER ! 692: printk("including file %s\n\n", tib); ! 693: #endif ! 694: interpret_source(tib); ! 695: continue; ! 696: } ! 697: ! 698: if (!strcmp(tib, "[']")) { ! 699: xt_t xt; ! 700: parse_word(f, tib); ! 701: xt = findword(tib); ! 702: if (*state == 0) { ! 703: #ifdef CONFIG_DEBUG_INTERPRETER ! 704: printk ! 705: ("writing address of %s to stack\n\n", ! 706: tib); ! 707: #endif ! 708: PUSH_xt(xt); ! 709: } else { ! 710: #ifdef CONFIG_DEBUG_INTERPRETER ! 711: printk("writing lit, addr(%s) to dict\n\n", ! 712: tib); ! 713: #endif ! 714: writecell(LIT); /* lit */ ! 715: writecell((cell)xt); ! 716: } ! 717: continue; ! 718: /* we have no error detection here */ ! 719: } ! 720: ! 721: if (!strcasecmp(tib, "s\"")) { ! 722: int cnt; ! 723: cell loco; ! 724: ! 725: cnt = parse(f, tib, '"'); ! 726: #ifdef CONFIG_DEBUG_INTERPRETER ! 727: printk("compiling string %s\n", tib); ! 728: #endif ! 729: loco = dicthead + (6 * sizeof(cell)); ! 730: writecell(LIT); ! 731: writecell(pointer2cell(dict) + loco); ! 732: writecell(LIT); ! 733: writecell((ucell)cnt); ! 734: writecell(DOBRANCH); ! 735: loco = cnt + sizeof(cell) - 1; ! 736: loco &= ~(sizeof(cell) - 1); ! 737: writecell(loco); ! 738: memcpy(dict + dicthead, tib, cnt); ! 739: dicthead += cnt; ! 740: paddict(sizeof(cell)); ! 741: continue; ! 742: } ! 743: ! 744: /* look if tib is in dictionary. */ ! 745: /* should the dictionary be searched before the builtins ? */ ! 746: res = findword(tib); ! 747: if (res) { ! 748: u8 flags = read_byte((u8*)cell2pointer(res) - ! 749: sizeof(cell) - 1); ! 750: #ifdef CONFIG_DEBUG_INTERPRETER ! 751: printk("%s is 0x%" FMT_CELL_x "\n", tib, (ucell) res); ! 752: #endif ! 753: if (!(*state) || (flags & 3)) { ! 754: #ifdef CONFIG_DEBUG_INTERPRETER ! 755: printk("executing %s, %" FMT_CELL_d ! 756: " (flags: %s %s)\n", ! 757: tib, res, ! 758: (flags & 1) ? "immediate" : "", ! 759: (flags & 2) ? "compile-only" : ""); ! 760: #endif ! 761: PC = (ucell)res; ! 762: enterforth(res); ! 763: } else { ! 764: #ifdef CONFIG_DEBUG_INTERPRETER ! 765: printk("writing %s to dict\n\n", tib); ! 766: #endif ! 767: writecell((cell)res); ! 768: } ! 769: continue; ! 770: } ! 771: ! 772: /* if not look if it's a number */ ! 773: if (tib[0] == '-') ! 774: num = strtoll(tib, &test, read_ucell(base)); ! 775: else ! 776: num = strtoull(tib, &test, read_ucell(base)); ! 777: ! 778: ! 779: if (*test != 0) { ! 780: /* what is it?? */ ! 781: printk("%s:%d: %s is not defined.\n\n", srcfilenames[cursrc - 1], srclines[cursrc - 1], tib); ! 782: errors++; ! 783: #ifdef CONFIG_DEBUG_INTERPRETER ! 784: continue; ! 785: #else ! 786: return -1; ! 787: #endif ! 788: } ! 789: ! 790: if (*state == 0) { ! 791: #ifdef CONFIG_DEBUG_INTERPRETER ! 792: printk("pushed %" FMT_CELL_x " to stack\n\n", num); ! 793: #endif ! 794: PUSH(num); ! 795: } else { ! 796: #ifdef CONFIG_DEBUG_INTERPRETER ! 797: printk("writing lit, %" FMT_CELL_x " to dict\n\n", num); ! 798: #endif ! 799: writecell(LIT); /* lit */ ! 800: writecell(num); ! 801: } ! 802: } ! 803: ! 804: fclose(f); ! 805: cursrc--; ! 806: ! 807: return 0; ! 808: } ! 809: ! 810: static int build_dictionary(void) ! 811: { ! 812: ucell lfa = 0; ! 813: unsigned int i; ! 814: ! 815: /* we need a temporary place for latest outside the dictionary */ ! 816: latest = &lfa; ! 817: ! 818: /* starting a new dictionary: clear dicthead */ ! 819: dicthead = 0; ! 820: ! 821: #ifdef CONFIG_DEBUG_DICTIONARY ! 822: printk("building dictionary, %d primitives.\nbuilt words:", ! 823: sizeof(wordnames) / sizeof(void *)); ! 824: #endif ! 825: ! 826: for (i = 0; i < sizeof(wordnames) / sizeof(void *); i++) { ! 827: if (strlen(wordnames[i]) != 0) { ! 828: fcreate((char *) wordnames[i], i); ! 829: #ifdef CONFIG_DEBUG_DICTIONARY ! 830: printk(" %s", wordnames[i]); ! 831: #endif ! 832: } ! 833: } ! 834: #ifdef CONFIG_DEBUG_DICTIONARY ! 835: printk(".\n"); ! 836: #endif ! 837: ! 838: /* get last/latest and state */ ! 839: state = buildvariable("state", 0); ! 840: last = buildvariable("forth-last", 0); ! 841: latest = buildvariable("latest", 0); ! 842: ! 843: *latest = target_ucell(pointer2cell(latest)-2*sizeof(cell)); ! 844: ! 845: base=buildvariable("base", 10); ! 846: ! 847: buildconstant("/c", sizeof(u8)); ! 848: buildconstant("/w", sizeof(u16)); ! 849: buildconstant("/l", sizeof(u32)); ! 850: buildconstant("/n", sizeof(ucell)); ! 851: buildconstant("/x", sizeof(u64)); ! 852: ! 853: reveal(); ! 854: if (verbose) { ! 855: printk("Dictionary initialization finished.\n"); ! 856: } ! 857: return 0; ! 858: } ! 859: ! 860: /* ! 861: * functions used by primitives ! 862: */ ! 863: ! 864: int availchar(void) ! 865: { ! 866: int tmp; ! 867: if( cursrc < 1 ) { ! 868: interruptforth |= FORTH_INTSTAT_STOP; ! 869: /* return -1 in order to exit the loop in key() */ ! 870: return -1; ! 871: } ! 872: ! 873: tmp = getc( srcfiles[cursrc-1] ); ! 874: if (tmp != EOF) { ! 875: ungetc(tmp, srcfiles[cursrc-1]); ! 876: return -1; ! 877: } ! 878: ! 879: fclose(srcfiles[--cursrc]); ! 880: ! 881: return availchar(); ! 882: } ! 883: ! 884: int get_inputbyte( void ) ! 885: { ! 886: int tmp; ! 887: ! 888: if( cursrc < 1 ) { ! 889: interruptforth |= FORTH_INTSTAT_STOP; ! 890: return 0; ! 891: } ! 892: ! 893: tmp = getc( srcfiles[cursrc-1] ); ! 894: ! 895: /* Update current line number */ ! 896: if (tmp == '\n') { ! 897: srclines[cursrc - 1]++; ! 898: } ! 899: ! 900: if (tmp != EOF) { ! 901: return tmp; ! 902: } ! 903: ! 904: fclose(srcfiles[--cursrc]); ! 905: ! 906: return get_inputbyte(); ! 907: } ! 908: ! 909: void put_outputbyte( int c ) ! 910: { ! 911: if (console) ! 912: fputc(c, console); ! 913: } ! 914: ! 915: /* ! 916: * segmentation fault handler. linux specific? ! 917: */ ! 918: ! 919: static void ! 920: segv_handler(int signo __attribute__ ((unused)), ! 921: siginfo_t * si, void *context __attribute__ ((unused))) ! 922: { ! 923: static int count = 0; ! 924: ucell addr = 0xdeadbeef; ! 925: ! 926: if (count) { ! 927: printk("Died while dumping forth dictionary core.\n"); ! 928: goto out; ! 929: } ! 930: ! 931: count++; ! 932: ! 933: if (PC >= pointer2cell(dict) && PC <= pointer2cell(dict) + dicthead) ! 934: addr = read_cell(cell2pointer(PC)); ! 935: ! 936: printk("panic: segmentation violation at %p\n", (char *)si->si_addr); ! 937: printk("dict=%p here=%p(dict+0x%" FMT_CELL_x ") pc=0x%" FMT_CELL_x "(dict+0x%" FMT_CELL_x ")\n", ! 938: dict, dict + dicthead, dicthead, PC, PC - pointer2cell(dict)); ! 939: printk("dstackcnt=%d rstackcnt=%d instruction=%" FMT_CELL_x "\n", ! 940: dstackcnt, rstackcnt, addr); ! 941: ! 942: printdstack(); ! 943: printrstack(); ! 944: ! 945: printk("Writing dictionary core file\n"); ! 946: write_dictionary("forth.dict.core"); ! 947: ! 948: out: ! 949: exit(1); ! 950: } ! 951: ! 952: /* ! 953: * allocate memory and prepare engine for memory management. ! 954: */ ! 955: ! 956: static void init_memory(void) ! 957: { ! 958: memset(memory, 0, MEMORY_SIZE); ! 959: ! 960: /* we push start and end of memory to the stack ! 961: * so that it can be used by the forth word QUIT ! 962: * to initialize the memory allocator. ! 963: * Add a cell to the start address so we don't end ! 964: * up with a start address of zero during bootstrap ! 965: */ ! 966: ! 967: PUSH(pointer2cell(memory)+sizeof(cell)); ! 968: PUSH(pointer2cell(memory) + MEMORY_SIZE-1); ! 969: } ! 970: ! 971: ! 972: void ! 973: include_file( const char *name ) ! 974: { ! 975: FILE *file; ! 976: ! 977: if( cursrc >= sizeof(srcfiles)/sizeof(srcfiles[0]) ) { ! 978: printk("\npanic: Maximum include depth reached!\n"); ! 979: exit(1); ! 980: } ! 981: ! 982: file = fopen_include( name ); ! 983: if( !file ) { ! 984: printk("\npanic: Failed opening file '%s'\n", name ); ! 985: exit(1); ! 986: } ! 987: } ! 988: ! 989: ! 990: void ! 991: encode_file( const char *name ) ! 992: { ! 993: FILE *file = fopen_include(name); ! 994: int size; ! 995: ! 996: if( !file ) { ! 997: printk("\npanic: Can't open '%s'\n", name ); ! 998: exit(1); ! 999: } ! 1000: fseek( file, 0, SEEK_END ); ! 1001: size = ftell( file ); ! 1002: fseek( file, 0, SEEK_SET ); ! 1003: ! 1004: if (verbose) { ! 1005: printk("\nEncoding %s [%d bytes]\n", name, size ); ! 1006: } ! 1007: fread( dict + dicthead, size, 1, file ); ! 1008: PUSH( pointer2cell(dict + dicthead) ); ! 1009: PUSH( size ); ! 1010: dicthead += size; ! 1011: } ! 1012: ! 1013: ! 1014: static void run_dictionary(char *basedict, char *confile) ! 1015: { ! 1016: if(!basedict) ! 1017: return; ! 1018: ! 1019: read_dictionary(basedict); ! 1020: PC = (ucell)findword("initialize"); ! 1021: ! 1022: if (!PC) { ! 1023: if (verbose) { ! 1024: printk("Unable to find initialize word in dictionary %s; ignoring\n", basedict); ! 1025: } ! 1026: return; ! 1027: } ! 1028: ! 1029: if(!srcfiles[0]) { ! 1030: cursrc = 1; ! 1031: srcfiles[cursrc-1] = stdin; ! 1032: } ! 1033: ! 1034: dstackcnt=0; ! 1035: rstackcnt=0; ! 1036: ! 1037: init_memory(); ! 1038: if (verbose) ! 1039: printk("Jumping to dictionary %s...\n", basedict); ! 1040: ! 1041: /* If a console file has been specified, open it */ ! 1042: if (confile) ! 1043: console = fopen(confile, "w"); ! 1044: ! 1045: srcbasedict = basedict; ! 1046: ! 1047: enterforth((xt_t)PC); ! 1048: ! 1049: /* Close the console file */ ! 1050: if (console) ! 1051: fclose(console); ! 1052: } ! 1053: ! 1054: static void new_dictionary(const char *source) ! 1055: { ! 1056: build_dictionary(); ! 1057: ! 1058: interpret_source((char *)source); ! 1059: ! 1060: if (verbose || errors > 0) { ! 1061: printk("interpretion finished. %d errors occured.\n", ! 1062: errors); ! 1063: } ! 1064: } ! 1065: ! 1066: /* ! 1067: * main loop ! 1068: */ ! 1069: ! 1070: #define BANNER "OpenBIOS bootstrap kernel. (C) 2003-2006 Patrick Mauritz, Stefan Reinauer\n"\ ! 1071: "This software comes with absolutely no warranty. "\ ! 1072: "All rights reserved.\n\n" ! 1073: ! 1074: #ifdef __GLIBC__ ! 1075: #define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \ ! 1076: " -h|--help show this help\n" \ ! 1077: " -V|--version print version and exit\n" \ ! 1078: " -v|--verbose print debugging information\n" \ ! 1079: " -I|--include dir add dir to include path\n" \ ! 1080: " -d|--source-dictionary bootstrap.dict\n" \ ! 1081: " use this dictionary as base\n" \ ! 1082: " -D|--target-dictionary output.dict\n" \ ! 1083: " write to output.dict\n" \ ! 1084: " -c|--console output.log\n" \ ! 1085: " write kernel console output to log file\n" \ ! 1086: " -s|--segfault install segfault handler\n" \ ! 1087: " -M|--dependency-dump file\n" \ ! 1088: " dump dependencies in Makefile format\n\n" \ ! 1089: " -x|--hexdump output format is C language hex dump\n" ! 1090: #else ! 1091: #define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \ ! 1092: " -h show this help\n" \ ! 1093: " -V print version and exit\n" \ ! 1094: " -v print debugging information\n" \ ! 1095: " -I add dir to include path\n" \ ! 1096: " -d bootstrap.dict\n" \ ! 1097: " use this dictionary as base\n" \ ! 1098: " -D output.dict\n" \ ! 1099: " write to output.dict\n" \ ! 1100: " -c output.log\n" \ ! 1101: " write kernel console output to log file\n" \ ! 1102: " -s install segfault handler\n\n" \ ! 1103: " -M file dump dependencies in Makefile format\n\n" \ ! 1104: " -x output format is C language hex dump\n" ! 1105: #endif ! 1106: ! 1107: int main(int argc, char *argv[]) ! 1108: { ! 1109: struct sigaction sa; ! 1110: ! 1111: unsigned char *ressources=NULL; /* All memory used by us */ ! 1112: const char *dictname = NULL; ! 1113: char *basedict = NULL; ! 1114: char *consolefile = NULL; ! 1115: char *depfilename = NULL; ! 1116: ! 1117: unsigned char *bootstrapdict[2]; ! 1118: int c, cnt, hexdump = 0; ! 1119: ! 1120: const char *optstring = "VvhsI:d:D:c:M:x?"; ! 1121: ! 1122: while (1) { ! 1123: #ifdef __GLIBC__ ! 1124: int option_index = 0; ! 1125: static struct option long_options[] = { ! 1126: {"version", 0, NULL, 'V'}, ! 1127: {"verbose", 0, NULL, 'v'}, ! 1128: {"help", 0, NULL, 'h'}, ! 1129: {"segfault", 0, NULL, 's'}, ! 1130: {"include", 1, NULL, 'I'}, ! 1131: {"source-dictionary", 1, NULL, 'd'}, ! 1132: {"target-dictionary", 1, NULL, 'D'}, ! 1133: {"console", 1, NULL, 'c'}, ! 1134: {"dependency-dump", 1, NULL, 'M'}, ! 1135: {"hexdump", 0, NULL, 'x'}, ! 1136: }; ! 1137: ! 1138: /* ! 1139: * option handling ! 1140: */ ! 1141: ! 1142: c = getopt_long(argc, argv, optstring, long_options, ! 1143: &option_index); ! 1144: #else ! 1145: c = getopt(argc, argv, optstring); ! 1146: #endif ! 1147: if (c == -1) ! 1148: break; ! 1149: ! 1150: switch (c) { ! 1151: case 'V': ! 1152: printk("Version " OPENBIOS_VERSION_STR "\n"); ! 1153: return 0; ! 1154: case 'h': ! 1155: case '?': ! 1156: printk("Version " OPENBIOS_VERSION_STR "\n" USAGE, ! 1157: argv[0]); ! 1158: return 0; ! 1159: case 'v': ! 1160: verbose = 1; ! 1161: break; ! 1162: case 's': ! 1163: segfault = 1; ! 1164: break; ! 1165: case 'I': ! 1166: #ifdef CONFIG_DEBUG_INTERPRETER ! 1167: printk("adding '%s' to include path\n", optarg); ! 1168: #endif ! 1169: add_includepath(optarg); ! 1170: break; ! 1171: case 'd': ! 1172: if (!basedict) { ! 1173: basedict = optarg; ! 1174: } ! 1175: break; ! 1176: case 'D': ! 1177: if(!dictname) { ! 1178: dictname = optarg; ! 1179: } ! 1180: break; ! 1181: case 'c': ! 1182: if (!consolefile) { ! 1183: consolefile = optarg; ! 1184: } ! 1185: break; ! 1186: case 'M': ! 1187: if (!depfilename) { ! 1188: depfilename = optarg; ! 1189: } ! 1190: break; ! 1191: case 'x': ! 1192: hexdump = 1; ! 1193: break; ! 1194: default: ! 1195: return 1; ! 1196: } ! 1197: } ! 1198: ! 1199: if (!dictname) { ! 1200: dictname = "bootstrap.dict"; ! 1201: } ! 1202: if (verbose) { ! 1203: printk(BANNER); ! 1204: printk("Using source dictionary '%s'\n", basedict); ! 1205: printk("Dumping final dictionary to '%s'\n", dictname); ! 1206: printk("Dumping dependencies to '%s'\n", depfilename); ! 1207: } ! 1208: ! 1209: if (argc < optind) { ! 1210: printk(USAGE, argv[0]); ! 1211: return 1; ! 1212: } ! 1213: ! 1214: if (depfilename) { ! 1215: depfile = fopen(depfilename, "w"); ! 1216: if (!depfile) { ! 1217: printk("panic: can't write to dependency file '%s'.\n", ! 1218: depfilename); ! 1219: exit(1); ! 1220: } ! 1221: fprintf(depfile, "%s:", dictname); ! 1222: } ! 1223: ! 1224: /* ! 1225: * Get all required resources ! 1226: */ ! 1227: ! 1228: ! 1229: ressources = malloc(MEMORY_SIZE + (2 * DICTIONARY_SIZE) + TRAMPOLINE_SIZE); ! 1230: if (!ressources) { ! 1231: printk("panic: not enough memory on host system.\n"); ! 1232: return 1; ! 1233: } ! 1234: ! 1235: #ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH ! 1236: base_address=(unsigned long)ressources; ! 1237: #endif ! 1238: ! 1239: memory = (ucell *)ressources; ! 1240: ! 1241: bootstrapdict[0] = ressources + MEMORY_SIZE; ! 1242: bootstrapdict[1] = ressources + MEMORY_SIZE + DICTIONARY_SIZE; ! 1243: trampoline = (ucell *)(ressources + MEMORY_SIZE + DICTIONARY_SIZE + DICTIONARY_SIZE); ! 1244: ! 1245: #ifdef CONFIG_DEBUG_INTERPRETER ! 1246: printf("memory: %p\n",memory); ! 1247: printf("dict1: %p\n",bootstrapdict[0]); ! 1248: printf("dict2: %p\n",bootstrapdict[1]); ! 1249: printf("trampoline: %p\n",trampoline); ! 1250: printf("size=%d, trampoline_size=%d\n",MEMORY_SIZE + (2 * ! 1251: DICTIONARY_SIZE) + TRAMPOLINE_SIZE, ! 1252: TRAMPOLINE_SIZE); ! 1253: #endif ! 1254: ! 1255: if (trampoline == NULL) { ! 1256: /* We're using side effects which is to some extent nasty */ ! 1257: printf("WARNING: no trampoline!\n"); ! 1258: } else { ! 1259: init_trampoline(trampoline); ! 1260: } ! 1261: ! 1262: if (!segfault) { ! 1263: if (verbose) ! 1264: printk("Installing SIGSEGV handler..."); ! 1265: ! 1266: sa.sa_sigaction = segv_handler; ! 1267: sigemptyset(&sa.sa_mask); ! 1268: sa.sa_flags = SA_SIGINFO | SA_NODEFER; ! 1269: sigaction(SIGSEGV, &sa, NULL); ! 1270: ! 1271: if (verbose) ! 1272: printk("done.\n"); ! 1273: } ! 1274: ! 1275: /* ! 1276: * Now do the real work ! 1277: */ ! 1278: ! 1279: for (cnt=0; cnt<2; cnt++) { ! 1280: if (verbose) { ! 1281: printk("Compiling dictionary %d/%d\n", cnt+1, 2); ! 1282: } ! 1283: dict=bootstrapdict[cnt]; ! 1284: if(!basedict) { ! 1285: new_dictionary(argv[optind]); ! 1286: } else { ! 1287: for (c=argc-1; c>=optind; c--) ! 1288: include_file(argv[c]); ! 1289: ! 1290: run_dictionary(basedict, consolefile); ! 1291: } ! 1292: if (depfile) { ! 1293: fprintf(depfile, "\n"); ! 1294: fclose(depfile); ! 1295: depfile = NULL; ! 1296: } ! 1297: if(errors) ! 1298: break; ! 1299: } ! 1300: ! 1301: #ifndef CONFIG_DEBUG_INTERPRETER ! 1302: if (errors) ! 1303: printk("dictionary not dumped to file.\n"); ! 1304: else ! 1305: #endif ! 1306: { ! 1307: relocation_table( bootstrapdict[0], bootstrapdict[1], dicthead); ! 1308: if (hexdump) { ! 1309: write_dictionary_hex(dictname); ! 1310: } else { ! 1311: write_dictionary(dictname); ! 1312: } ! 1313: } ! 1314: ! 1315: free(ressources); ! 1316: ! 1317: if (errors) ! 1318: return 1; ! 1319: else ! 1320: return 0; ! 1321: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.