/* * Load a Unicode mapping file */ static void load_unicode_file(char *filename, unicode_map_t map[256], char *infile, int linenum) { osfildef *fp; int linenum_u; /* open the unicode file */ fp = osfoprs(filename, OSFTTEXT); if (fp == 0) { printf("%s: line %d: unable to open unicode mapping file \"%s\"\n", infile, linenum, filename); return; } /* read it */ for (linenum_u = 1 ;; ++linenum_u) { char buf[256]; char *p; unsigned int n1; unsigned int n2; /* read the next line */ if (osfgets(buf, sizeof(buf), fp) == 0) break; /* skip leading spaces */ for (p = buf ; isspace(*p) ; ++p) ; /* if it's blank or starts with a comment, ignore it */ if (*p == 0x1a || *p == '#' || *p == '\n' || *p == '\r' || *p == '\0') continue; /* read the first number - this is the native character value */ if (read_number(&n1, &p, filename, linenum_u, TRUE)) break; /* read the second number */ if (read_number(&n2, &p, filename, linenum_u, FALSE)) break; /* set the association */ map[n1].unicode_val = n2; } /* done with the file */ osfcls(fp); }
/** * fileReadLine * */ IEC_UINT fileReadLine(IEC_UDINT hFile, IEC_CHAR *szData, IEC_UINT uLen) { IEC_UINT uRes = OK; if (hFile == 0) { RETURN(ERR_INVALID_PARAM); } szData = osfgets(szData, uLen, (VMF_FILE)hFile); if (szData == 0) { if (osfeof((VMF_FILE)hFile) != 0) { return ERR_FILE_EOF; } uRes = ERR_FILE_READ; } RETURN(uRes); }
/* * load a configuration file */ void TadsNetConfig::read(osfildef *fp, CVmMainClientIfc *clientifc) { /* read the file line by line */ for (int linenum = 1 ; ; ++linenum) { /* read the next line */ char buf[512]; if (osfgets(buf, sizeof(buf), fp) == 0) break; /* skip leading whitespace */ char *p; for (p = buf ; isspace(*p) ; ++p) ; /* skip blank lines and comments */ if (*p == '\0' || *p == '#') continue; /* the variable name is the first token on the line */ char *name = p; /* find the end of the name: the next space or '=' */ for ( ; *p != '\0' && !isspace(*p) && *p != '=' ; ++p) ; char *name_end = p; /* skip spaces */ for ( ; isspace(*p) ; ++p) ; /* make sure we stopped at a '=' */ if (*p != '=') { char *msg = t3sprintf_alloc( "Missing '=' in web config file at line %d", linenum); clientifc->display_error(0, 0, msg, FALSE); t3free(msg); continue; } /* null-terminate the name */ *name_end = '\0'; /* skip spaces after the '=' */ for (++p ; isspace(*p) ; ++p) ; /* the value starts here */ char *val = p; /* * the value is the rest of the line, minus trailing spaces and * newlines */ for (p += strlen(p) ; p > val && (isspace(*(p-1)) || *(p-1) == '\n' || *(p-1) == '\r') ; --p) ; /* null-terminate the value */ *p = '\0'; /* add the variable */ TadsNetConfigVar *var = set(name, val); /* check that this is a variable name we recognize */ static const char *known_vars[] = { "serverid", "storage.domain", "storage.rootpath", "storage.apikey", "watchdog" }; int found = FALSE; for (size_t i = 0 ; i < countof(known_vars) ; ++i) { if (var->matchname(known_vars[i])) { found = TRUE; break; } } /* warn if we didn't find it among the known variables */ if (!found) { char *msg = t3sprintf_alloc( "Warning: unknown variable name '%s' in web config file " "at line %d\n", name, linenum); clientifc->display_error(0, 0, msg, FALSE); t3free(msg); } } }
/* * 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) { 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; }