/* * open for writing */ void CVmFile::open_write(const char *fname, os_filetype_t typ) { /* try opening the underlying OS file for binary writing */ fp_ = osfopwb(fname, typ); /* if that failed, throw an error */ if (fp_ == 0) err_throw(VMERR_CREATE_FILE); }
int main(int argc, char **argv) { CResLoader *res_loader; CTcHostIfc *hostifc; int curarg; int fatal_error_count = 0; osfildef *fpout = 0; int next_local = 0; CVmFile *imgfile = 0; CVmFile *objfile = 0; const char *imgfname; int success; char pathbuf[OSFNMAX]; static const char tool_data[4] = { 't', 's', 't', 'L' }; /* initialize for testing */ test_init(); /* create the host interface object */ hostifc = new CTcHostIfcStdio(); /* create a resource loader */ os_get_special_path(pathbuf, sizeof(pathbuf), argv[0], OS_GSP_T3_RES); res_loader = new CResLoader(pathbuf); /* initialize the compiler */ CTcMain::init(hostifc, res_loader, 0); err_try { /* scan arguments */ for (curarg = 1 ; curarg < argc ; ++curarg) { char *p; /* get the argument string for easy reference */ p = argv[curarg]; /* if it's not an option, we're done */ if (*p != '-') break; if (*(p + 1) == 'v') { /* set verbose mode */ G_tcmain->set_verbosity(TRUE); } else { /* * invalid usage - consume all the arguments and fall * through to the usage checker */ curarg = argc; break; } } /* check arguments */ if (curarg + 2 > argc) { /* terminate the compiler */ CTcMain::terminate(); /* delete our objects */ delete res_loader; /* exit with an error */ errexit("usage: test_link [options] obj-file [obj-file [...]] " "image-file\n" "options:\n" " -v - verbose error messages"); } /* set up an output file */ imgfname = argv[argc - 1]; fpout = osfopwb(imgfname, OSFTT3IMG); if (fpout == 0) errexit("unable to open image file"); imgfile = new CVmFile(); imgfile->set_file(fpout, 0); /* read the object files */ for ( ; curarg < argc - 1 ; ++curarg) { osfildef *fpobj; /* open this object file */ fpobj = osfoprb(argv[curarg], OSFTT3OBJ); if (fpobj == 0) { printf("unable to open object file \"%s\"\n", argv[curarg]); goto done; } /* note the loading */ printf("loading %s\n", argv[curarg]); /* set up the CVmFile object for it */ objfile = new CVmFile(); objfile->set_file(fpobj, 0); /* read the object file */ G_cg->load_object_file(objfile, argv[curarg]); /* done with the object file */ delete objfile; objfile = 0; } /* check for unresolved externals */ if (G_prs->check_unresolved_externs()) goto done; /* write the image file */ G_cg->write_to_image(imgfile, 0, tool_data); done: ; } err_catch(exc) { /* * if it's not a general internal or fatal error, log it; don't * log general errors, since these will have been logged as * specific internal errors before being thrown */ if (exc->get_error_code() != TCERR_INTERNAL_ERROR && exc->get_error_code() != TCERR_FATAL_ERROR) G_tok->log_error(TC_SEV_FATAL, exc->get_error_code()); /* count the fatal error */ ++fatal_error_count; } err_end; /* report errors */ fprintf(stderr, "Warnings: %d\n" "Errors: %d\n" "Longest string: %d, longest list: %d\n", G_tcmain->get_warning_count(), G_tcmain->get_error_count() + fatal_error_count, G_cg->get_max_str_len(), G_cg->get_max_list_cnt()); /* * note whether or not the compilation was successful - it succeeded * if we had no errors or fatal errors */ success = (G_tcmain->get_error_count() + fatal_error_count == 0); /* delete the object file object (this closes the file) */ delete imgfile; /* if we have an open object file, close it */ if (objfile != 0) delete objfile; /* * if any errors occurred, delete the object file in the external * file system - this prevents us from leaving around an incomplete * or corrupted image file when compilation fails, and helps * 'make'-type tools realize that they must generate the image file * target again on the next build, even if source files didn't * change */ if (!success) osfdel(imgfname); /* shut down the compiler */ CTcMain::terminate(); /* done with the res loader */ delete res_loader; /* delete the host interface */ delete hostifc; /* show any unfreed memory */ t3_list_memory_blocks(0); /* * terminate - exit with a success indication if we had no errors * (other than warnings); exit with an error indication otherwise */ return (success ? OSEXSUCC : OSEXFAIL); }
/* * Main entrypoint */ int main(int argc, char **argv) { int curarg; unsigned char input_map[256]; unsigned char output_map[256]; unsigned char input_map_set[256]; unsigned char output_map_set[256]; unsigned char *p; int i; osfildef *fp; char *infile; char *outfile; int linenum; static char sig[] = CMAP_SIG_S100; int strict_mode = FALSE; char id[5]; char ldesc[CMAP_LDESC_MAX_LEN + 1]; size_t len; unsigned char lenbuf[2]; char *sys_info; entity_map_t *entity_first; entity_map_t *entity_last; /* no parameters have been specified yet */ memset(id, 0, sizeof(id)); ldesc[0] = '\0'; sys_info = 0; /* we have no entities in our entity mapping list yet */ entity_first = entity_last = 0; /* scan options */ for (curarg = 1 ; curarg < argc && argv[curarg][0] == '-' ; ++curarg) { if (!stricmp(argv[curarg], "-strict")) { /* they want extra warnings */ strict_mode = TRUE; } else { /* consume all remaining options so we get a usage message */ curarg = argc; break; } } /* check for required arguments */ if (curarg + 1 >= argc) { printf("usage: mkchrtab [options] <source> <dest>\n" " <source> is the input file\n" " <dest> is the output file\n" "Options:\n" " -strict warn if any codes 128-255 are unassigned\n"); #if 0 /* * The information about what goes in the file made the message way too * long, so this has been removed. Users will want to the documentation * instead of the usage message for information this detailed, so it * didn't seem useful to keep it in here. */ printf("\n" "The source file contains one entry per line, as follows:\n" "\n" "Set the internal character set identifier, which can be up " "to four letters long\n" "(note that the mapping file MUST contain an ID entry):\n" " ID = id\n" "\n"); printf("Set the internal character set's full display name:\n" " LDESC = full name of character set\n" "\n" "Set system-dependent extra information (the meaning varies " "by system):\n" " EXTRA_SYSTEM_INFO = info-string\n" "\n" "Set the native default character:\n" " NATIVE_DEFAULT = charval\n" "Set the internal default character:\n" " INTERNAL_DEFAULT = charval\n"); printf("Load Unicode mapping files:\n" " UNICODE NATIVE=native-mapping INTERNAL=internal-mapping\n" "\n" "Reversibly map a native character code to an internal code:\n" " native <-> internal\n" "\n" "Map a native code to an internal code, and map the internal " "code back\nto a different native code:\n" " native -> internal -> native\n" "\n" "Map a native code to an internal code, where the internal " "code is already\nmapped to a native code by a previous line:\n" " native -> internal\n" "\n"); printf("Map an internal code to a native code, where the native " "code is already\nmapped to an internal code by a previous " "line:\n" " native <- internal\n" "\n" "Map an HTML entity name to a native code or string:\n" " &entity = internal-code [internal-code ...]\n" "\n" "Numbers can be specified in decimal (default), octal (by " "prefixing the number\nwith a zero, as in '037'), or hex (by " "prefixing the number with '0x', as in\n'0xb2'). A number " "can also be entered as a character by enclosing the\n" "character in single quotes.\n" "\n" "Blank lines and lines starting with a pound sign ('#') are " "ignored.\n"); #endif /* 0 */ os_term(OSEXFAIL); } /* get the input and output filenames */ infile = argv[curarg]; outfile = argv[curarg + 1]; /* * initialize the tables - by default, a character code in one * character set maps to the same code in the other character set */ for (p = input_map, i = 0 ; i < sizeof(input_map)/sizeof(input_map[0]) ; ++i, ++p) *p = (unsigned char)i; for (p = output_map, i = 0 ; i < sizeof(output_map)/sizeof(output_map[0]) ; ++i, ++p) *p = (unsigned char)i; /* * initialize the "set" flags all to false, since we haven't set any * of the values yet -- we'll use these flags to detect when the * user attempts to set the same value more than once, so that we * can issue a warning (multiple mappings are almost certainly in * error) */ for (i = 0 ; i < sizeof(input_map_set)/sizeof(input_map_set[0]) ; ++i) input_map_set[i] = output_map_set[i] = FALSE; /* open the input file */ fp = osfoprs(infile, OSFTTEXT); if (fp == 0) { printf("error: unable to open input file \"%s\"\n", infile); os_term(OSEXFAIL); } /* parse the input file */ for (linenum = 1 ; ; ++linenum) { char buf[256]; char *p; unsigned int n1, n2, n3; int set_input; int set_output; /* presume we're going to set both values */ set_input = set_output = TRUE; /* read the next line */ if (osfgets(buf, sizeof(buf), fp) == 0) break; /* scan off leading spaces */ for (p = buf ; isspace(*p) ; ++p) ; /* if this line is blank, or starts with a '#', ignore it */ if (*p == '\0' || *p == '\n' || *p == '\r' || *p == '#') continue; /* check for special directives */ if (isalpha(*p) || *p == '_') { char *sp; char *val; size_t vallen; size_t idlen; /* find the end of the directive name */ for (sp = p ; isalpha(*sp) || *sp == '_' ; ++sp) ; idlen = sp - p; /* find the equals sign, if present */ for (val = sp ; isspace(*val) ; ++val) ; if (*val == '=') { /* skip the '=' and any spaces that follow */ for (++val ; isspace(*val) ; ++val) ; /* find the end of the value */ for (sp = val ; *sp != '\n' && *sp != '\r' && *sp != '\0' ; ++sp) ; /* note its length */ vallen = sp - val; } else { /* there's no value */ val = 0; } /* see what we have */ if (id_matches(p, idlen, "id")) { /* this directive requires a value */ if (val == 0) goto val_required; /* ID's can never be more than four characters long */ if (vallen > 4) { printf("%s: line %d: ID too long - no more than four " "characters are allowed\n", infile, linenum); } else { /* remember the ID */ memcpy(id, val, vallen); id[vallen] = '\0'; } } else if (id_matches(p, idlen, "ldesc")) { /* this directive requires a value */ if (val == 0) goto val_required; /* make sure it fits */ if (vallen > sizeof(ldesc) - 1) { printf("%s: line %d: LDESC too long - no more than %u " "characters are allowed\n", infile, linenum, sizeof(ldesc) - 1); } else { /* remember the ldesc */ memcpy(ldesc, val, vallen); ldesc[vallen] = '\0'; } } else if (id_matches(p, idlen, "extra_system_info")) { /* this directive requires a value */ if (val == 0) goto val_required; /* allocate space for it */ sys_info = (char *)malloc(vallen + 1); memcpy(sys_info, val, vallen); sys_info[vallen] = '\0'; } else if (id_matches(p, idlen, "native_default")) { unsigned int nval; int i; /* this directive requires a value */ if (val == 0) goto val_required; /* parse the character value */ if (read_number(&nval, &val, infile, linenum, TRUE)) continue; /* apply the default */ for (i = 128 ; i < 256 ; ++i) { /* set the default only if we haven't mapped this one */ if (!output_map_set[i]) output_map[i] = nval; } } else if (id_matches(p, idlen, "internal_default")) { unsigned int nval; int i; /* this directive requires a value */ if (val == 0) goto val_required; /* parse the character value */ if (read_number(&nval, &val, infile, linenum, TRUE)) continue; /* apply the default */ for (i = 128 ; i < 256 ; ++i) { /* apply the default only if we haven't set this one */ if (!input_map_set[i]) input_map[i] = nval; } } else if (id_matches(p, idlen, "unicode")) { /* skip the 'unicode' string and any intervening spaces */ for (p += idlen ; isspace(*p) ; ++p) ; /* parse the unicode files */ parse_unicode_files(p, strlen(p), infile, linenum, input_map, input_map_set, output_map, output_map_set, &entity_first, &entity_last); } else { /* unknown directive */ printf("%s: line %d: invalid directive '%.*s'\n", infile, linenum, idlen, p); } /* done processing this line */ continue; /* come here if the directive needs a value and there isn't one */ val_required: printf("%s: line %d: '=' required with directive '%.*s'\n", infile, linenum, idlen, p); continue; } /* check for an entity name */ if (*p == '&') { entity_map_t *mapp; /* skip the '&' */ ++p; /* * parse the entity - if it succeeds, link the resulting * mapping entry into our list */ mapp = parse_entity(p, infile, linenum); if (mapp != 0) { if (entity_last == 0) entity_first = mapp; else entity_last->nxt = mapp; entity_last = mapp; } /* done */ continue; } /* read the first number */ if (read_number(&n1, &p, infile, linenum, TRUE)) continue; /* determine which operator we have */ if (*p == '<') { /* make sure it's "<->" or "<-" */ if (*(p+1) == '-' && *(p+2) != '>') { /* skip the operator */ p += 2; /* * This is a "from" translation - it only affects the * output mapping from the internal character set to the * native character set. Read the second number. There * is no third number, since we don't want to change the * input mapping. */ if (read_number(&n2, &p, infile, linenum, TRUE)) continue; /* * The forward translation is not affected; set only the * output translation. Note that the first number was * the output (native) value for the internal index in * the second number, so move the first value to n3. */ n3 = n1; set_input = FALSE; } else if (*(p+1) == '-' && *(p+2) == '>') { /* skip it */ p += 3; /* * this is a reversible translation, so we only need one * more number - the third number is implicitly the same * as the first */ n3 = n1; if (read_number(&n2, &p, infile, linenum, TRUE)) continue; } else { printf("%s: line %d: invalid operator - expected <->\n", infile, linenum); continue; } } else if (*p == '-') { /* make sure it's "->" */ if (*(p+1) != '>') { printf("%s: line %d: invalid operator - expected ->\n", infile, linenum); continue; } /* skip it */ p += 2; /* get the next number */ if (read_number(&n2, &p, infile, linenum, TRUE)) continue; /* * we may or may not have a third number - if we have * another -> operator, read the third number; if we don't, * the reverse translation is not affected by this entry */ if (*p == '-') { /* make sure it's "->" */ if (*(p+1) != '>') { printf("%s: line %d: invalid operator - expected ->\n", infile, linenum); continue; } /* skip it */ p += 2; /* read the third number */ if (read_number(&n3, &p, infile, linenum, TRUE)) continue; } else { /* * There's no third number - the reverse translation is * not affected by this line. */ set_output = FALSE; } } else { printf("%s: line %d: invalid operator - expected " "-> or <-> or <-\n", infile, linenum); continue; } /* make sure we're at the end of the line, and warn if not */ if (*p != '\0' && *p != '\n' && *p != '\r' && *p != '#') printf("%s: line %d: extra characters at end of line ignored\n", infile, linenum); /* set the input mapping, if necessary */ if (set_input) { /* warn the user if this value has already been set before */ if (input_map_set[n1]) printf("%s: line %d: warning - native character %u has " "already been\n mapped to internal value %u\n", infile, linenum, n1, input_map[n1]); /* set it */ input_map[n1] = n2; /* note that it's been set */ input_map_set[n1] = TRUE; } /* set the output mapping, if necessary */ if (set_output) { /* warn the user if this value has already been set before */ if (output_map_set[n2]) printf("%s: line %d: warning - internal character %u has " "already been\n mapped to native value %u\n", infile, linenum, n2, input_map[n2]); /* set it */ output_map[n2] = n3; /* note that it's been set */ output_map_set[n2] = TRUE; } } /* we're done with the input file */ osfcls(fp); /* * It's an error if we didn't get an ID or LDESC */ if (id[0] == '\0') { printf("Error: No ID was specified. An ID is required.\n"); os_term(OSEXFAIL); } else if (ldesc[0] == '\0') { printf("Error: No LDESC was specified. An LDESC is required.\n"); os_term(OSEXFAIL); } /* open the output file */ fp = osfopwb(outfile, OSFTCMAP); if (fp == 0) { printf("error: unable to open output file \"%s\"\n", outfile); os_term(OSEXFAIL); } /* write our signature */ if (osfwb(fp, sig, sizeof(sig))) printf("error writing signature to output file\n"); /* write the ID and LDESC */ len = strlen(ldesc) + 1; oswp2(lenbuf, len); if (osfwb(fp, id, 4) || osfwb(fp, lenbuf, 2) || osfwb(fp, ldesc, len)) printf("error writing ID information to output file\n"); /* write the mapping tables */ if (osfwb(fp, input_map, sizeof(input_map)) || osfwb(fp, output_map, sizeof(output_map))) printf("error writing character maps to output file\n"); /* write the extra system information if present */ if (sys_info != 0) { /* write it out, with the "SYSI" flag so we know it's there */ len = strlen(sys_info) + 1; oswp2(lenbuf, len); if (osfwb(fp, "SYSI", 4) || osfwb(fp, lenbuf, 2) || osfwb(fp, sys_info, len)) printf("error writing EXTRA_SYSTEM_INFO to output file\n"); /* we're done with the allocated buffer now */ free(sys_info); } /* * Write the entity mapping list, if we have any entities */ if (entity_first != 0) { entity_map_t *entp; entity_map_t *next_entity; char lenbuf[2]; char cvalbuf[2]; /* write out the entity list header */ if (osfwb(fp, "ENTY", 4)) printf("error writing entity marker to output file\n"); /* run through the list, writing out each entry */ for (entp = entity_first ; entp != 0 ; entp = next_entity) { /* write out this entity */ oswp2(lenbuf, entp->exp_len); oswp2(cvalbuf, entp->html_char); if (osfwb(fp, lenbuf, 2) || osfwb(fp, cvalbuf, 2) || osfwb(fp, entp->expansion, entp->exp_len)) { printf("error writing entity mapping to output file\n"); break; } /* remember the next entity before we delete this one */ next_entity = entp->nxt; /* we're done with this entity, so we can delete it now */ free(entp); } /* * write out the end marker, which is just a length marker and * character marker of zero */ oswp2(lenbuf, 0); oswp2(cvalbuf, 0); if (osfwb(fp, lenbuf, 2) || osfwb(fp, cvalbuf, 2)) printf("error writing entity list end marker to output file\n"); } /* write the end-of-file marker */ if (osfwb(fp, "$EOF", 4)) printf("error writing end-of-file marker to output file\n"); /* done with the output file */ osfcls(fp); /* if we're in strict mode, check for unassigned mappings */ if (strict_mode) { int in_cnt, out_cnt; int cnt; /* count unassigned characters */ for (i = 128, in_cnt = out_cnt = 0 ; i < 256 ; ++i) { if (!input_map_set[i]) ++in_cnt; if (!output_map_set[i]) ++out_cnt; } /* if we have any unassigned native characters, list them */ if (in_cnt != 0) { printf("\nUnassigned native -> internal mappings:\n "); for (i = 128, cnt = 0 ; i < 256 ; ++i) { if (!input_map_set[i]) { /* go to a new line if necessary */ if (cnt >= 16) { printf("\n "); cnt = 0; } /* display this item */ printf("%3d ", i); ++cnt; } } printf("\n"); } /* list unassigned internal characters */ if (out_cnt != 0) { printf("\nUnassigned internal -> native mappings:\n "); for (i = 128, cnt = 0 ; i < 256 ; ++i) { if (!output_map_set[i]) { /* go to a new line if necessary */ if (cnt >= 16) { printf("\n "); cnt = 0; } /* display this item */ printf("%3d ", i); ++cnt; } } printf("\n"); } } /* success */ os_term(OSEXSUCC); return OSEXSUCC; }
int main(int argc, char **argv) { CResLoader *res_loader; CTcHostIfc *hostifc; int curarg; int fatal_error_count = 0; osfildef *fpout = 0; CVmFile *imgfile = 0; CTcUnasSrcCodeStr *unas_in; CTcUnasOutStdio unas_out; CTPNStmProg *node; const char *image_fname; int success; int unasm = FALSE; uchar xor_mask = 0; char pathbuf[OSFNMAX]; /* initialize for testing */ test_init(); /* create the host interface object */ hostifc = new CTcHostIfcStdio(); /* create a resource loader */ os_get_special_path(pathbuf, sizeof(pathbuf), argv[0], OS_GSP_T3_RES); res_loader = new CResLoader(pathbuf); /* initialize the compiler */ CTcMain::init(hostifc, res_loader, "us-ascii"); /* use test reporting mode */ G_tok->set_test_report_mode(TRUE); G_tcmain->set_test_report_mode(TRUE); /* create the disassembler input stream */ unas_in = new CTcUnasSrcCodeStr(G_cs); err_try { static const char tool_data[4] = { 't', 's', 't', 'P' }; /* scan options */ for (curarg = 1 ; curarg < argc ; ++curarg) { char *p; /* get the argument string for easy reference */ p = argv[curarg]; /* if it's not an option, we're done */ if (*p != '-') break; /* if it's a -I argument, use it */ if (*(p + 1) == 'I') { char *path; /* * if it's with this argument, read it, otherwise move * on to the next argument */ if (*(p + 2) == '\0') path = argv[++curarg]; else path = p + 2; /* add the directory to the include path list */ G_tok->add_inc_path(path); } else if (*(p + 1) == 'v') { /* set verbose mode */ G_tcmain->set_verbosity(TRUE); } else if (*(p + 1) == 'u') { /* note unassembly mode */ unasm = TRUE; } else { /* * invalid usage - consume all the arguments and fall * through to the usage checker */ curarg = argc; break; } } /* check arguments */ if (curarg + 2 != argc) { /* terminate the compiler */ CTcMain::terminate(); /* delete our objects */ delete res_loader; /* exit with an error */ errexit("usage: test_prs [options] <source-file> <image-file>\n" "options:\n" " -Idir - add dir to include path\n" " -v - verbose error messages"); } /* add the default system include directory to the include path */ os_get_special_path(pathbuf, sizeof(pathbuf), argv[0], OS_GSP_T3_INC); G_tok->add_inc_path(pathbuf); /* set up the tokenizer with the main input file */ if (G_tok->set_source(argv[curarg], argv[curarg])) errexit("unable to open source file"); /* set up an output file */ image_fname = argv[curarg+1]; fpout = osfopwb(image_fname, OSFTT3IMG); if (fpout == 0) errexit("unable to open image file"); imgfile = new CVmFile(); imgfile->set_file(fpout, 0); /* read the first token */ G_tok->next(); /* parse at the top level */ node = G_prs->parse_top(); /* if errors occurred during parsing, stop here */ if (G_tcmain->get_error_count() != 0 || node == 0) goto done; /* fold symbolic constants for all nodes */ node->fold_constants(G_prs->get_global_symtab()); /* if errors occurred during constant folding, stop now */ if (G_tcmain->get_error_count() != 0) goto done; /* generate code and write the image file */ node->build_image(imgfile, xor_mask, tool_data); /* if errors occurred during code generation, stop now */ if (G_tcmain->get_error_count() != 0) goto done; /* disassemble the result if desired */ if (unasm) CTcT3Unasm::disasm(unas_in, &unas_out); done: ; } err_catch(exc) { /* * if it's not a general internal or fatal error, log it; don't * log general errors, since these will have been logged as * specific internal errors before being thrown */ if (exc->get_error_code() != TCERR_INTERNAL_ERROR && exc->get_error_code() != TCERR_FATAL_ERROR) G_tok->log_error(TC_SEV_FATAL, exc->get_error_code()); /* count the fatal error */ ++fatal_error_count; } err_end; /* report errors */ fprintf(stderr, "Warnings: %d\n" "Errors: %d\n" "Longest string: %d, longest list: %d\n", G_tcmain->get_warning_count(), G_tcmain->get_error_count() + fatal_error_count, G_cg->get_max_str_len(), G_cg->get_max_list_cnt()); /* * note whether or not the compilation was successful - it succeeded * if we had no errors or fatal errors */ success = (G_tcmain->get_error_count() + fatal_error_count == 0); /* delete the image file object (this closes the file) */ delete imgfile; /* * if any errors occurred, delete the image file in the external * file system - this prevents us from leaving around an incomplete * or corrupted image file when compilation fails, and helps * 'make'-type tools realize that they must generate the image file * target again on the next build, even if source files didn't * change */ if (!success) osfdel(image_fname); /* delete the disassembler input object */ delete unas_in; /* shut down the compiler */ CTcMain::terminate(); /* done with the res loader */ delete res_loader; /* delete the host interface */ delete hostifc; /* show any unfreed memory */ t3_list_memory_blocks(0); /* * terminate - exit with a success indication if we had no errors * (other than warnings); exit with an error indication otherwise */ return (success ? OSEXSUCC : OSEXFAIL); }
int main(int argc, char **argv) { CResLoader *res_loader; CTcHostIfc *hostifc; int curarg; int fatal_error_count = 0; node_entry *node_head = 0; node_entry *node_tail = 0; osfildef *fpout = 0; CVmFile *imgfile = 0; ulong next_obj_id = 1; uint next_prop_id = 1; int next_local = 0; CTcTokFileDesc *desc; long linenum; CTcUnasSrcCodeStr *unas_in; CTcUnasOutStdio unas_out; char pathbuf[OSFNMAX]; /* initialize for testing */ test_init(); /* create the host interface object */ hostifc = new CTcHostIfcStdio(); /* create a resource loader */ os_get_special_path(pathbuf, sizeof(pathbuf), argv[0], OS_GSP_T3_RES); res_loader = new CResLoader(pathbuf); /* initialize the compiler */ CTcMain::init(hostifc, res_loader, 0); /* create the disassembler input stream */ unas_in = new CTcUnasSrcCodeStr(G_cs); err_try { /* scan -I arguments */ for (curarg = 1 ; curarg < argc ; ++curarg) { char *p; /* get the argument string for easy reference */ p = argv[curarg]; /* if it's not an option, we're done */ if (*p != '-') break; /* if it's a -I argument, use it */ if (*(p + 1) == 'I') { char *path; /* * if it's with this argument, read it, otherwise move * on to the next argument */ if (*(p + 2) == '\0') path = argv[++curarg]; else path = p + 2; /* add the directory to the include path list */ G_tok->add_inc_path(path); } else if (*(p + 1) == 'v') { /* set verbose mode */ G_tcmain->set_verbosity(TRUE); } else { /* * invalid usage - consume all the arguments and fall * through to the usage checker */ curarg = argc; break; } } /* check arguments */ if (curarg + 2 != argc) { /* terminate the compiler */ CTcMain::terminate(); /* delete our objects */ delete res_loader; /* exit with an error */ errexit("usage: test_prs [options] <source-file> <image-file>\n" "options:\n" " -Idir - add dir to include path\n" " -v - verbose error messages"); } /* set up the tokenizer with the main input file */ if (G_tok->set_source(argv[curarg], argv[curarg])) errexit("unable to open source file"); /* set up an output file */ fpout = osfopwb(argv[curarg+1], OSFTT3IMG); if (fpout == 0) errexit("unable to open image file"); imgfile = new CVmFile(); imgfile->set_file(fpout, 0); /* read the first token */ G_tok->next(); /* parse expressions */ for (;;) { CTcPrsNode *result; CTcSymbol *entry; /* if we're at end of file, we're done */ if (G_tok->getcur()->gettyp() == TOKT_EOF) break; /* check for our fake declarations */ switch(G_tok->getcur()->gettyp()) { case TOKT_OBJECT: /* add an object symbol */ G_tok->next(); entry = new CTcSymObj(G_tok->getcur()->get_text(), G_tok->getcur()->get_text_len(), FALSE, next_obj_id++, FALSE, TC_META_TADSOBJ, 0); G_prs->get_global_symtab()->add_entry(entry); /* skip the object name */ G_tok->next(); break; case TOKT_FUNCTION: /* add a function symbol */ G_tok->next(); entry = new CTcSymFunc(G_tok->getcur()->get_text(), G_tok->getcur()->get_text_len(), FALSE, 0, 0, FALSE, TRUE, FALSE, FALSE, FALSE); G_prs->get_global_symtab()->add_entry(entry); /* skip the function name */ G_tok->next(); break; case TOKT_LOCAL: /* add a local variable symbol */ G_tok->next(); entry = new CTcSymLocal(G_tok->getcur()->get_text(), G_tok->getcur()->get_text_len(), FALSE, FALSE, next_local++); G_prs->get_global_symtab()->add_entry(entry); /* skip the function name */ G_tok->next(); break; default: /* note the starting line */ desc = G_tok->get_last_desc(); linenum = G_tok->get_last_linenum(); /* parse an expression */ result = G_prs->parse_expr(); /* add it to our list */ if (result != 0) { node_entry *cur; /* create a new list entry */ cur = new node_entry(result, desc, linenum); /* link it at the end of our list */ cur->nxt = 0; if (node_tail != 0) node_tail->nxt = cur; else node_head = cur; node_tail = cur; } } /* parse a semicolon */ if (G_prs->parse_req_sem()) break; } /* * if there were no parse errors, run through our node list and * generate code */ if (G_tcmain->get_error_count() == 0) { /* * loop through our node list; generate code and then delete * each list entry */ while (node_head != 0) { node_entry *nxt; /* remember the next entry */ nxt = node_head->nxt; /* * set this line's descriptor as current, for error * reporting purposes */ G_tok->set_line_info(node_head->desc, node_head->linenum); /* fold symbolic constants */ node_head->node = node_head->node ->fold_constants(G_prs->get_global_symtab()); /* if it's a constant value, display it */ show_const(0, node_head->node); /* * generate code; for testing purposes, don't discard * anything, to ensure we perform all generation */ node_head->node->gen_code(FALSE, FALSE); /* disassemble this much */ unas_out.print("// line %lu\n", node_head->linenum); CTcT3Unasm::disasm(unas_in, &unas_out); /* delete this entry */ delete node_head; /* move on to the next entry */ node_head = nxt; } } } err_catch(exc) { /* * if it's not a general internal or fatal error, log it; don't * log general errors, since these will have been logged as * specific internal errors before being thrown */ if (exc->get_error_code() != TCERR_INTERNAL_ERROR && exc->get_error_code() != TCERR_FATAL_ERROR) G_tok->log_error(TC_SEV_FATAL, exc->get_error_code()); /* count the fatal error */ ++fatal_error_count; } err_end; /* report errors */ fprintf(stderr, "Warnings: %d\n" "Errors: %d\n" "Longest string: %d, longest list: %d\n", G_tcmain->get_warning_count(), G_tcmain->get_error_count() + fatal_error_count, G_cg->get_max_str_len(), G_cg->get_max_list_cnt()); /* delete the disassembler input object */ delete unas_in; /* shut down the compiler */ CTcMain::terminate(); /* done with the res loader */ delete res_loader; /* delete the image file */ delete imgfile; /* delete the host interface */ delete hostifc; /* show any unfreed memory */ t3_list_memory_blocks(0); /* success */ return 0; }
int main(int argc, char **argv) { osfildef *fpin; osfildef *fpout; CVmFile *file_in; CVmFile *file_out; int status; CVmHostIfc *hostifc; CVmMainClientConsole clientifc; int curarg; /* initialize for testing */ test_init(); /* initialize the error stack */ err_init(1024); /* start at the first argument */ curarg = 1; /* check usage */ if (curarg + 2 > argc) { printf("usage: t3pre <original-image> <new-image> [program-args]\n" "\n" "Runs preinitialization on the image file, writing a new " "image file\n" "with the state of the program after preinitialization.\n"); return OSEXFAIL; } /* open the files */ if ((fpin = osfoprb(argv[curarg], OSFTT3IMG)) == 0) { printf("Error opening original image file \"%s\"\n", argv[1]); return OSEXFAIL; } if ((fpout = osfopwb(argv[curarg + 1], OSFTT3IMG)) == 0) { printf("Error opening new image file \"%s\"\n", argv[2]); return OSEXFAIL; } /* create the CVmFile objects */ file_in = new CVmFile(); file_in->set_file(fpin, 0); file_out = new CVmFile(); file_out->set_file(fpout, 0); /* create our host interface */ hostifc = new CVmHostIfcStdio(argv[0]); /* run preinit and write the new image file */ err_try { /* load, run, and write */ vm_run_preinit(file_in, argv[1], file_out, hostifc, &clientifc, argv + curarg + 1, argc - curarg - 1, 0); /* note the success status */ status = OSEXSUCC; } err_catch(exc) { const char *msg; char buf[128]; /* look up the message */ msg = err_get_msg(vm_messages, vm_message_count, exc->get_error_code(), FALSE); /* if that failed, just show the error number */ if (msg == 0) { sprintf(buf, "[no message: code %d]", exc->get_error_code()); msg = buf; } /* show the message */ printf("VM Error: %s\n", msg); /* note the failure status */ status = OSEXFAIL; } err_end; /* delete the file objects, which will close the files */ delete file_in; delete file_out; /* terminate the error mechanism */ err_terminate(); /* delete our host interface object */ delete hostifc; /* log any memory leaks */ t3_list_memory_blocks(0); /* exit with appropriate results */ return status; }
int main(int argc, char **argv) { int curarg; osfildef *fpin; osfildef *fpout; char tmpfile[OSFNMAX + 1]; char inbuf[OSFNMAX + 1]; char *p; char *infile; char buf[128]; opdef *oplist = (opdef *)0; opctxdef opctx; int do_create = FALSE; /* print main banner */ rscptf("TADS Resource Manager version 2.2.4\n"); rscptf("Copyright (c) 1992, 1999 by Michael J. Roberts. "); rscptf("All Rights Reserved.\n"); if (argc < 2) usage(); /* set default parsing options */ opctx.restype = RESTYPE_DFLT; opctx.flag = OPFADD | OPFDEL; opctx.doing_type = FALSE; /* scan file options (these come before the filename) */ for (curarg = 1 ; curarg < argc ; ++curarg) { /* check if it's an option - if not, stop looking */ if (argv[curarg][0] != '-') break; /* check the option */ if (!stricmp(argv[curarg], "-create")) { /* note that we want to create the file */ do_create = TRUE; } else { rscptf("unrecognized file option \"%s\"", argv[curarg]); errexit("", 1); } } /* get the file name */ infile = argv[curarg++]; strcpy(inbuf, infile); os_defext(inbuf, "gam"); /* open the file for reading, unless we're creating a new file */ if (do_create) { /* creating - we have no input file */ fpin = 0; } else if ((fpin = osfoprb(inbuf, OSFTGAME)) == 0) { /* * not creating, so the file must already exist - it doesn't, so * issue an error and quit */ errexit("unable to open resource file", 1); } /* * if no operations are desired, and we're not creating a new file, * just list the existing file's contents and quit */ if (curarg == argc && fpin != 0) { rscproc(fpin, (osfildef *)0, 0); osfcls(fpin); os_term(OSEXSUCC); } /* * Create an output file. If we're creating a new file, create the * file named on the command line; otherwise, create a temporary * file that we'll write to while working and then rename to the * original input filename after we've finished with the original * input file. */ if (do_create) { /* create the new file */ if ((fpout = osfopwb(inbuf, OSFTGAME)) == 0) errexit("unable to create file", 1); /* report the creation */ rscptf("\nFile created.\n"); } else { /* generate a temporary filename */ strcpy(tmpfile, inbuf); for (p = tmpfile + strlen(tmpfile) ; p > tmpfile && *(p-1) != ':' && *(p-1) != '\\' && *(p-1) != '/' ; --p); strcpy(p, "$TADSRSC.TMP"); /* open the temporary file */ if ((fpout = osfopwb(tmpfile, OSFTGAME)) == 0) errexit("unable to create temporary file", 1); } /* see if we need to read a response file */ if (curarg < argc && argv[curarg][0] == '@') { osfildef *argfp; int l; char *p; if (!(argfp = osfoprt(argv[curarg]+1, OSFTTEXT))) errexit("unable to open response file", 1); for (;;) { if (!osfgets(buf, sizeof(buf), argfp)) break; l = strlen(buf); if (l && buf[l-1] == '\n') buf[--l] = '\0'; for (p = buf ; t_isspace(*p) ; ++p); if (!*p) continue; oplist = addop(oplist, p, &opctx); } osfcls(argfp); } else { for ( ; curarg < argc ; ++curarg) oplist = addop(oplist, argv[curarg], &opctx); } /* process the resources */ oplist = rscproc(fpin, fpout, oplist); /* make sure they all got processed */ for ( ; oplist != 0 ; oplist = oplist->opnxt) { if (!(oplist->opflag & OPFDONE)) rscptf("warning: resource \"%s\" not found\n", oplist->opres); } /* close files */ if (fpin != 0) osfcls(fpin); if (fpout != 0) osfcls(fpout); /* * if we didn't create a new file, remove the original input file * and rename the temp file to the original file name */ if (!do_create) { /* remove the original input file */ if (remove(inbuf)) errexit("error deleting input file", 1); /* rename the temp file to the output file */ if (rename(tmpfile, inbuf)) errexit("error renaming temporary file", 1); } /* success */ os_term(OSEXSUCC); return OSEXSUCC; }