From: Lynx Date: 000316 Short: Binary codefile support Type: Patch State: New Hello hackers'n'mudders.. For some strange reason I've been spending quite some time hacking around LDMud recently.. one of the outcomes is this implementation for storage of binary bytecode into .b files. The format is MudOS-incompatible, as it allows textual patching of strings and function names (without having to maintain its original length) .. ;-) The driver is capable to recreate the program code from the bytecode except for function calls to inherited functions which cause a runtime exception. After a while of trying I decided I've had enough of having to understand all of the inner workings of lpmud, so here goes the code "as is". Anyone willing to find the missing link, go ahead.. if you find it let me know so I can finish the thing up with proper timestamp comparisons and include dependencies. It's really almost done, it just needs someone to look at it from a different perspective. P.S. Other Work-In-Progress: I'm looking into integrating generic on-the-fly gzip-decompression (zlib) for any files the driver tries to access, as well as builtin SSLtunneling using OpenSSL. Interested? -- Carlo von Loesch - Internet Broadcast and Chat Application Research psyc: the new protocol for conferencing and messaging - http://psyc.pages.de/ *** simulate.c-orig Fri Mar 3 05:45:17 2000 --- simulate.c Fri Mar 3 05:45:04 2000 *************** *** 1417,1426 **** /* First check that the c-file exists. */ (void)strcpy(fname+name_length, ".c"); if (ixstat(fname, &c_st) == -1) { /* The file does not exist - maybe it's a virtual object */ ! svalue_t *svp; push_volatile_string(fname); --- 1417,1436 ---- /* First check that the c-file exists. */ (void)strcpy(fname+name_length, ".c"); + + #ifdef BINARIES + /* let's see if we can load the bytecode rightaway --symlynX */ + if ( (prog = load_binary(fname, depth)) ) + { + if (d_flag > 1) fprintf(stderr, "%s loaded bytecode for %s\n" + , time_stamp(), fname); + } else { + #endif + /* otherwise see if the source code is available */ if (ixstat(fname, &c_st) == -1) { /* The file does not exist - maybe it's a virtual object */ ! /* "virtual object" is a bad name. let's call it a "named clone" */ svalue_t *svp; push_volatile_string(fname); *************** *** 1578,1596 **** error("Error in loading object '%s' " "(inheritance failed)\n", name); } } /* handling of inherit_file */ } /* while() - compilation loop */ /* Did the compilation succeed? */ if (num_parse_error > 0) { ! error("Error in loading object '%s'\n", name); } /* We got the program. Now create the blueprint to hold it. */ prog = compiled_prog; #ifdef INITIALIZATION_BY___INIT ob = get_empty_object(prog->num_variables); --- 1588,1611 ---- error("Error in loading object '%s' " "(inheritance failed)\n", name); } + } /* handling of inherit_file */ } /* while() - compilation loop */ /* Did the compilation succeed? */ if (num_parse_error > 0) { ! error("Error in loading object '%s'\n", name); } /* We got the program. Now create the blueprint to hold it. */ prog = compiled_prog; + #ifdef BINARIES + (void) save_binary(prog); + } + #endif #ifdef INITIALIZATION_BY___INIT ob = get_empty_object(prog->num_variables); *************** *** 5286,5289 **** } /* f_copy_file() */ /***************************************************************************/ - --- 5301,5303 ---- *** /ve/t/ldmud-157/src/swap.c Thu Nov 25 14:10:38 1999 --- swap.c Fri Mar 3 05:29:20 2000 *************** *** 1892,1894 **** --- 1892,2189 ---- /***************************************************************************/ + #ifdef BINARIES + + /* + * Written while peeking into the equivalent MudOS code.. --symlynX + */ + + //efine BCDIR "bytecode/" + #define LDBTAG "LDBIN/b\n" + + program_t *load_binary (char *file_name, int inheridepth) { + program_t *p; + bytecode_p bc; + // TODO: buf sizes! + // buf can contain whole web pages as string, so lets make it big + char fn[256], buf[16384]; + FILE *f; + char *t; + unsigned long i,j; + unsigned short l; + p_int k; + funflag_t flags; + fun_hdr_p fun; + + // TODO: ask master ob if we should binload this + // strcpy(fn, BCDIR); + // if (stat(fn, &st) == -1) return NULL; + strcpy(fn, file_name); + fn[strlen(fn) - 1] = 'b'; /* change .c ending to .b */ + + // TODO: check if source is available and newer + if (!(f = fopen(fn, "r"))) return NULL; + + #if 1 + fgets(buf, sizeof buf, f); + if (strcmp(buf, LDBTAG)) { + if (d_flag) fprintf(stderr, "%s load: Wrong binary for %s\n", + time_stamp(), fn); + fclose(f); + return NULL; + } + if (comp_flag) fprintf(stderr, "%s Loading binary %s ... ", + time_stamp(), fn); + #else + // scanf doesnt always work + if (!fscanf(f, LDBTAG "/%d.%d\n", &i, &j) || i != LDBMAJ ) { + if (comp_flag) fprintf(stderr, "%s load: Wrong binary for %s\n", + time_stamp(), fn); + fclose(f); + return NULL; + } + if (comp_flag) fprintf(stderr, "%s Loading binary %s (%d/%d) ... ", + time_stamp(), fn, i,j); + #endif + // TODO: add driver-id, include file info + // or any other guess why this file may be too old + + fread((char *) &k, sizeof(p_int), 1, f); + if (! (p = xalloc(k)) ) return NULL; + fread((char *) p, k, sizeof(char), f); + #if 0 + fprintf(stderr, "total:\t$%lx\n", p->total_size); + // fprintf(stderr, "start:\t$%lx\n", (unsigned long)p); + // fprintf(stderr, "end:\t$%lx\n", p->total_size + (unsigned long)p); + fprintf(stderr, "prg:\t$%lx\n", (unsigned long)p->program); + fprintf(stderr, "lines:\t$%lx\n", (unsigned long)p->line_numbers); + // if (p->line_numbers) + // fprintf(stderr, "lines0:\t$%lx\n", (unsigned long)p->line_numbers[0]); + fprintf(stderr, "fnames:\t$%lx\n", (unsigned long)p->function_names); + fprintf(stderr, "funcs:\t$%lx\n", (unsigned long)p->functions); + fprintf(stderr, "string:\t$%lx\n", (unsigned long)p->strings); + fprintf(stderr, "vars:\t$%lx\n", (unsigned long)p->variable_names); + fprintf(stderr, "inheri:\t$%lx\n", (unsigned long)p->inherit); + fprintf(stderr, "flags:\t$%lx\n", (unsigned long)p->flags); + #endif + // have to locate the line numbers in myself + bc = p->line_numbers; + locate_in(p); + p->line_numbers = (bytecode_p) ( (int)p + (int)bc ); + // maybe we should add a "be_transparent" flag to locate_in() + + if (p->total_size != k) + fprintf(stderr, "Size mismatch %lx != %lx\n", k, p->total_size); + fread(&buf, 1, sizeof(char), f); + if (buf[0] != '\n') { + if (comp_flag) fprintf(stderr, "Broken bytecode file\n"); + fclose(f); + return NULL; + } + // inherits + for (i = 0; i < p->num_inherited; i++) { + object_t *ob; + + fgets(buf, sizeof buf, f); + l = strlen(buf); + buf[--l] = (char)0; + if (comp_flag) + if (!i) fprintf(stderr, "needs %s\n", buf); + else fprintf(stderr, "%s %s also needs %s\n", + time_stamp(), fn, buf); + + // lets see how clean ldmud is + //ob = load_object(buf, MY_TRUE, inheridepth-1); + ob = lookfor_object(buf, MY_TRUE); + + if (!ob || ob->flags & O_DESTRUCTED) { + fprintf(stderr, "inheritance failed\n"); + fclose(f); + return NULL; + } + p->inherit[i].prog = ob->prog; + // fprintf(stderr, "%s inherits %s\n", fn, + // p->inherit[i].prog->name); + } + // variable names + for (i = 0; i < p->num_variables; i++) { + fgets(buf, sizeof buf, f); + l = strlen(buf); + buf[--l] = (char)0; + // fprintf(stderr, "in var %s\n", buf); + p->variable_names[i].name = make_shared_string(buf); + } + // function names, when available + for (i = 0; i < p->num_function_names; i++) { + program_t *progp; + inherit_t *inheritp; + + j = p->function_names[i]; + // flags = p->functions[j]; + // if (flags & NAME_INHERITED) continue; + fgets(buf, sizeof buf, f); + l = strlen(buf); + buf[--l] = (char)0; + + progp = p; + while ((flags = progp->functions[j]) & NAME_INHERITED) { + inheritp = &progp->inherit[flags & INHERIT_MASK]; + j -= inheritp->function_index_offset; + progp = inheritp->prog; + } + fun = progp->program + (flags & FUNSTART_MASK); + #if 0 + memcpy (&t, FUNCTION_NAMEP(fun), sizeof t); + if (progp != p && t) + fprintf(stderr, "<inhfn:\t$%lx -> $%lx for func %d/%d %s\n", + (long)(FUNCTION_NAMEP(fun)) - (long)p, t, i,j, t); + #endif + if (flags & NAME_INHERITED) continue; + + // the following took me quite a while to figure out :-( + t = make_shared_string(buf); + memcpy (FUNCTION_NAMEP(fun), &t, sizeof t); + #if 0 + // paranoid check + fun = p->program + (flags & FUNSTART_MASK); + memcpy (&t, FUNCTION_NAMEP(fun), sizeof t); + fprintf(stderr, "fna:\t$%lx -> $%lx for func %d/%d %s\n", + (long)fun - (long)p, t, i,j, t); + #endif + // fprintf(stderr, "in function %d/%d '%s'\n", i,j, buf); + } + // strings + for (i = 0; i < p->num_strings; i++) { + fread((char *) &l, sizeof l, 1, f); + fread(&buf, l+1, 1, f); + buf[l] = (char)0; + p->strings[i] = make_shared_string(buf); + // fprintf(stderr, "in string %s\n", buf); + } + + p->name = make_shared_string(file_name); + // p->swap_num = -1; + + total_prog_block_size += p->total_size; + total_num_prog_blocks++; + + // no type checking for binaries + //p->argument_types = NULL; + //p->type_start = NULL; + + p->ref = 0; + reference_prog(p, "load_binary"); + for (i = 0; i < p->num_inherited; i++) + reference_prog(p->inherit[i].prog, "binherit"); + + fclose(f); + if (comp_flag) + if (p->num_inherited) fprintf(stderr, "%s %s done\n", + time_stamp(), fn); + else fputs("done\n", stderr); + return p; + } + + int save_binary (program_t *p) { + program_t ptmp; + char fn[256]; // TODO: FNSIZE + FILE *f; + char *t; + unsigned short i,j,l; + funflag_t flags; + fun_hdr_p fun; + + // TODO: ask master ob if we should binsave this + // TODO: mkdirhier_fopen function + // strcpy(fn, BCDIR); + // if (stat(fn, &st) == -1) return -1; + strcpy(fn, p->name); + fn[strlen(fn) - 1] = 'b'; /* change .c ending to .b */ + // if (comp_flag) fprintf(stderr, + // " (save %s as %d.%d) ", fn, LDBMAJ,LDBMIN); + + if (!(f = fopen(fn, "w"))) return -2; + fputs(LDBTAG, f); + // TODO: add driver-id, include file info + // or any other guess why this file may be too old + + // save a copy of the prog struct + memcpy(&ptmp, p, sizeof ptmp); + locate_out(p); + #if 0 + fprintf(stderr, "total:\t$%lx\n", p->total_size); + // fprintf(stderr, "start:\t$%lx\n", (unsigned long)p); + // fprintf(stderr, "end:\t$%lx\n", p->total_size + (unsigned long)p); + fprintf(stderr, "prg:\t$%lx\n", (unsigned long)p->program); + fprintf(stderr, "lines:\t$%lx\n", (unsigned long)p->line_numbers); + // if (p->line_numbers) + // fprintf(stderr, "lines0:\t$%lx\n", (unsigned long)ptmp.line_numbers[0]); + fprintf(stderr, "fnames:\t$%lx\n", (unsigned long)p->function_names); + fprintf(stderr, "funcs:\t$%lx\n", (unsigned long)p->functions); + fprintf(stderr, "string:\t$%lx\n", (unsigned long)p->strings); + fprintf(stderr, "vars:\t$%lx\n", (unsigned long)p->variable_names); + fprintf(stderr, "inheri:\t$%lx\n", (unsigned long)p->inherit); + fprintf(stderr, "flags:\t$%lx\n", (unsigned long)p->flags); + #endif + // store program struct + fwrite((char *) &p->total_size, sizeof(p_int), 1, f); + fwrite((char *) p, p->total_size, sizeof(char), f); + fputs("\n", f); + + // locate_in without using the function (as it is non-transparent) + memcpy(p, &ptmp, sizeof ptmp); + + // inherited classes + for (i = 0; i < p->num_inherited; i++) + fprintf(f, "%s\n", p->inherit[i].prog->name); + + // variable names + for (i = 0; i < p->num_variables; i++) + fprintf(f, "%s\n", p->variable_names[i].name); + #if 0 + // function pointers (includes nameless functions) + for (i = 0; i < p->num_functions; i++) { + flags = p->functions[i]; + fwrite((char *) &flags, sizeof flags, 1, f); + } + #endif + // function names, when available + for (i = 0; i < p->num_function_names; i++) { + program_t *progp; + inherit_t *inheritp; + + j = p->function_names[i]; + // flags = p->functions[j]; + // if (flags & NAME_INHERITED) continue; + progp = p; + while ((flags = progp->functions[j]) & NAME_INHERITED) { + inheritp = &progp->inherit[flags & INHERIT_MASK]; + j -= inheritp->function_index_offset; + progp = inheritp->prog; + } + fun = progp->program + (flags & FUNSTART_MASK); + memcpy (&t, FUNCTION_NAMEP(fun), sizeof t); + #if 0 + if (progp != p) + fprintf(stderr, ">inhfn:\t$%lx -> $%lx for func %d/%d %s\n", + (long)(FUNCTION_NAMEP(fun)) - (long)p, t, i,j, t); + #endif + // fprintf(stderr, "out function %d/%d %s\n", i,j, t); + fprintf(f, "%s\n", t); + } + // strings + for (i = 0; i < p->num_strings; i++) { + t = p->strings[i]; + l = strlen(t); + fwrite((char *) &l, sizeof l, 1, f); + fprintf(f, "%s\n", t); + // fprintf(stderr, "stri:\t$%lx = %lx (%s)\n", t, findstring( t ), t); + } + + fclose(f); + // if (comp_flag) fprintf(stderr, " (done saving)\n"); + // (void)load_binary(p->name); + return 0; + } + + #endif