void dumpString(const int stringId) { FILE *f; int len, cnt; unsigned char *p; sprintf(cfilename, cfmt, stringId); if((f = fopen(cfile, "wt")) == NULL) { pxerror("creating ", cfile); exit(102); } fprintf(f, "const char %s[] = {\n\t", strg[stringId].name); p = (unsigned char*)strg[stringId].text; if(string[stringId].size > 1) { for(len = string[stringId].size, cnt = 9; --len;) { char ch; dumpCh(f, ch = *p++); putc(',', f); putc(' ', f); if(--cnt == 0 || ch == '\n') { putc('\n', f); putc('\t', f); cnt = 9; } } } if(string[stringId].size) dumpCh(f, *p); fputs("\n};\n", f); fclose(f); }
int main(int argc, char **argv) { FILE *dat, *inc; int rc; unsigned long size; string_count_t cnt; /* current string number */ string_size_t lsize; int makeLib = 0; *fDIR = '\0'; if(argv[1] && stricmp(argv[1], "/lib") == 0) { --argc; ++argv; makeLib = 1; } // output directory if (argc > 1 && stricmp(argv[1], "/dir") == 0) { --argc; ++argv; strcpy(fDIR, argv[1]); --argc; ++argv; } if (argc > 2) { puts("FIXSTRS - Generate STRINGS.DAT and STRINGS.H for a language\n" "Useage: FIXSTRS [/lib] [language] [directory]\n" "\tIf no language is specified, only the default strings are read.\n" "\tThe <language>.LNG file must reside in the current directory.\n" "Note: DEFAULT.LNG must be present in the current directory, too."); return 127; } in_file = 1; if((rc = loadFile(fTXT)) != 0) return rc; in_file = 2; if(argc > 1 && (rc = loadFile(argv[1])) != 0) { --argc; ++argv; return rc; } /* Now all the strings are cached into memory */ if(maxCnt < 2) { fputs("No string definition found.\n", stderr); return 43; } /* Prepend a directory, if needed */ if (*fDIR) { strcpy(temp1, fDIR); logfile = strcat(temp1, logfile); } /* Create the LOG file */ if(argc > 1) { /* Only if a local LNG file was specified */ log = NULL; /* No LOG entry til this time */ for(cnt = 0; cnt < maxCnt; ++cnt) { switch(strg[cnt].flags & 3) { case 0: /* Er?? */ fputs("Internal error assigned string has no origin?!\n" , stderr); return 99; case 1: /* DEFAULT.LNG only */ if(!log && (log = fopen(logfile, "wt")) == NULL) { fprintf(stderr, "Cannot create logfile: '%s'\n" , logfile); goto breakLogFile; } fprintf(log, "%s: Missing from local LNG file\n" , strg[cnt].name); break; case 2: /* local.LNG only */ if(!log && (log = fopen(logfile, "wt")) == NULL) { fprintf(stderr, "Cannot create logfile: '%s'\n" , logfile); goto breakLogFile; } fprintf(log, "%s: No such string resource\n" , strg[cnt].name); break; case 3: /* OK */ break; } if(strg[cnt].flags & VERSION_MISMATCH) { if(!log && (log = fopen(logfile, "wt")) == NULL) { fprintf(stderr, "Cannot create logfile: '%s'\n" , logfile); goto breakLogFile; } fprintf(log, "%s: Version mismatch, current is: %u\n" , strg[cnt].name, strg[cnt].version); } if(strg[cnt].flags & VALIDATION_MISMATCH) { if(!log && (log = fopen(logfile, "wt")) == NULL) { fprintf(stderr, "Cannot create logfile: '%s'\n" , logfile); goto breakLogFile; } fprintf(log, "%s: printf() format string mismatch, should be: %s\n" , strg[cnt].name, strg[cnt].vstring); } } if(log) fclose(log); } breakLogFile: /* 1. Adjust the offset and generate the overall size */ for(size = string[0].size, cnt = 1; cnt < maxCnt; ++cnt) { string[cnt].index = string[cnt-1].index + string[cnt-1].size; size += string[cnt].size; } if(size >= 0x10000ul - sizeof(string_index_t) * maxCnt) { fputs("Overall size of strings exceeds 64KB limit\n", stderr); return 44; } if (*fDIR) { strcpy(temp1, fDIR); fDAT = strcat(temp1, fDAT); } /* 2. Open STRINGS.DAT and STRINGS.H and dump control information */ if ((dat = fopen(fDAT,"wb")) == NULL) { strcpy(temp2, "creating "); strcpy(temp2, fDAT); perror(temp2); return 36; } if (*fDIR) { strcpy(temp1, fDIR); fH = strcat(temp1, fH); } if ((inc = fopen(fH,"wt")) == NULL) { strcpy(temp2, "creating "); strcat(temp2, fH); perror(temp2); return 37; } puts("FIXSTRS: building STRINGS resource"); fputs("/*\n" " * This file was automatically generated by FIXSTRS.\n" " * Any modifications will be lost next time this tool\n" " * is invoked.\n" " */\n\n", inc); fprintf(inc,"#define STRINGS_ID \"%s%u\"\n" , id, STRING_RESOURCE_MINOR_ID); startResource(dat, RES_ID_STRINGS, STRING_RESOURCE_MINOR_ID); /* Preamble of STRINGS.DAT file */ fprintf(dat, "%s%u", id, STRING_RESOURCE_MINOR_ID); /* fwrite(id, sizeof(id) - 1, 1, dat); *//* file contents ID */ fwrite("\r\n\x1a", 4, 1, dat); /* text file full stop */ fputs("#define STRINGS_ID_TRAILER 4\n", inc); /* 4 additional bytes */ fputs("\n\n", inc); /* delimiter */ /* parameters of strings */ fwrite(&maxCnt, sizeof(maxCnt), 1, dat); /* number of strings */ lsize = (string_size_t)size; fwrite(&lsize, sizeof(lsize), 1, dat); /* total size of string text */ /* string control area */ fwrite(string, sizeof(string[0]), maxCnt, dat); /* append the strings */ for(cnt = 0; cnt < maxCnt; ++cnt) { fwrite(strg[cnt].text, string[cnt].size, 1, dat); if(makeLib) fprintf(inc, "extern const char %s[];\n", strg[cnt].name); fprintf(inc, "#define %-34s 0x%02x /* @ 0x%04x */\n" , strg[cnt].name, cnt, string[cnt].index); } fputs("\n/* END OF FILE */\n", inc); endResource(dat); fflush(dat); if(ferror(dat)) { strcpy(temp2, "Unspecific write error into "); strcat(temp2, fDAT); strcat(temp2, "\n"); fputs(temp2, stderr); return 38; } fflush(inc); if(ferror(inc)) { strcpy(temp2, "Unspecific write error into "); strcat(temp2, fH); strcat(temp2, "\n"); fputs(temp2, stderr); return 39; } fclose(dat); fclose(inc); if(makeLib) { mkdir(fDIR); #define fdmake inc #define ftc101 dat //cfilename[-1] = '\\'; //strcpy(cfilename, fDMAKEFILE); if (*fDIR) { strcpy(temp1, fDIR); cfile = strcat(temp1, fDMAKEFILE); cfilename = cfile + strlen(fDIR); } if((fdmake = fopen(cfile, "wt")) == NULL) { pxerror("creating ", cfile); return 100; } strcpy(cfilename, fTCMAKEFILE); if((ftc101 = fopen(cfile, "wt")) == NULL) { pxerror("creating ", cfile); return 101; } puts("FIXSTRS: building STRINGS library source files"); /********************** prologue */ fputs("\ #\n\ # A Makefile for ATTRIB\n\ # (c) osFree project,\n\ # author, date\n\ #\n\ \n\ PROJ = strings\n\ DESC = Control file attributes\n\ #defines object file names in format objname.$(O)\n\ srcfiles = ", fdmake); /********************* individual files */ for(cnt = 0; cnt < maxCnt; ++cnt) { dumpString(cnt); fprintf(fdmake, " &\n\t" objfmt1, cnt); } for(cnt = 0; cnt < maxCnt - 1; ++cnt) fprintf(ftc101, "+" objfmt " \n", cnt); fprintf(ftc101, "+" objfmt " \n", cnt); /********************** epilogue */ fputs("\n\n\ # defines additional options for C compiler\n\ ADD_COPT = -i=$(MYDIR)..$(SEP)include -i=$(MYDIR)..$(SEP)suppl\n\ \n\ !include $(%ROOT)/mk/libsdos.mk\n\ \n\ TARGETS = $(PATH)$(PROJ).lib\n\ \n\ $(TARGETS): $(OBJS)\n\ @$(MAKE) $(MAKEOPT) -f $(PATH)makefile.mk library=$(TARGETS) library install\n\ \n\ lib: $(TARGETS)\n\ \n", fdmake); fflush(ftc101); if(ferror(ftc101)) { strcpy(temp2, "Unspecific error writing to "); strcat(temp2, fTCMAKEFILE); puts(temp2); return 104; } fclose(ftc101); fflush(fdmake); if(ferror(fdmake)) { strcpy(temp2, "Unspecific error writing to "); strcat(temp2, fDMAKEFILE); puts(temp2); return 105; } fclose(fdmake); } return 0; }
int loadFile(const char * const fnam) { unsigned long linenr; char *p; read_state state = LOOKING_FOR_START; FILE *fin; dynstring text; /* Current text */ dynstring vstring; /* Validation string */ int version; text.text = vstring.text = 0; printf("FIXSTRS: loading file %s\n", fnam); join(fnam, fEXT); if((fin = fopen(fnam, "rt")) == NULL) { //&& (fin = fopen(temp, "rt")) == NULL) { pxerror("opening ", fnam); return 33; } linenr = 0; while (fgets(temp, sizeof(temp), fin)) { ++linenr; p = strchr(temp, '\0'); if(p[-1] != '\n') { fprintf(stderr, "Line %lu too long\n", linenr); return 41; } /* Cut trailing control characters */ while (--p >= temp && iscntrl(*p)); p[1] = '\0'; switch (state) { case LOOKING_FOR_START: switch(*temp) { case ':': { char *vers; if((vers = strchr(temp + 1, '#')) != 0) { *vers = '\0'; } /* Locate the string name */ for(cnt = 0; cnt < maxCnt; ++cnt) if(strcmp(strg[cnt].name, temp + 1) == 0) goto strnameFound; /* string name was not found --> create a new one */ ++maxCnt; strnameFound: if(!strg[cnt].name) { if((strg[cnt].name = strdup(temp + 1)) == 0) { fputs("Out of memory\n", stderr); return 80; } } vstring.length = text.length = 0; version = (vers && *++vers)? atoi(vers): 0; if(vers && strchr(vers, '%')) strg[cnt].flags |= PERFORM_VALIDATION; if(memcmp(strg[cnt].name, promptID, promptIDlen) == 0) state = GETTING_PROMPT_LINE_1; else state = GETTING_STRING; } break; default: while(p >= temp && isspace(*p)) --p; if(p >= temp) { fprintf(stderr, "Syntax error in line #%lu\n", linenr); return 44; } /** fall through **/ case '\0': case '#': break; } break; case GETTING_PROMPT_LINE_1: { char *p, *q, len; int ch; if((*temp == '.' || *temp == ',') && (temp[1] == '\0')) { fprintf(stderr, "%s: %s: prompt syntax error\n" , fnam, strg[cnt].name); return 41; } q = p = temp; while((ch = *p++) != 0) switch(ch) { case '\\': if(*p && (*q++ = mapBSEscape(&p)) == 0) { fprintf(stderr , "%s: %s: ASCII(0) is no valid key\n" , fnam, strg[cnt].name); return 49; } break; case '{': { char *h; int thisCh; if((p = strchr(h = p, '}')) == 0) { fprintf(stderr , "%s: %s: invalid symbolic key\n" , fnam, strg[cnt].name); return 46; } *p++ = 0; if((thisCh = mapSymKey(h)) == 0) { fprintf(stderr , "%s: %s: unknown symbolic key\n" , fnam, strg[cnt].name); return 47; } if(thisCh >= 256) { fprintf(stderr , "%s: %s: non-ASCII keys not supported, yet\n" , fnam, strg[cnt].name); return 55; } *q++ = thisCh; } break; case '[': fprintf(stderr , "%s: %s: brackets are not supported, yet\n" , fnam, strg[cnt].name); return 48; default: *q++ = ch; break; } *q = 0; if(q == temp) { fprintf(stderr , "%s: %s: empty key sequence\n" , fnam, strg[cnt].name); return 52; } if((unsigned)(q - temp) > 255) { fprintf(stderr , "%s: %s: too many keys\n" , fnam, strg[cnt].name); return 55; } len = (char)(q - temp); /* Prompts are PStrings in this form: LKKKKMMMM where number of K's == number of M's == L K -> key (1..255); M -> metakey (range 1..26); 0 < L < 256 */ if(!appMem(text, &len, 1) || !app(temp)) return 42; state = GETTING_PROMPT_LINE_2; } break; case GETTING_PROMPT_LINE_2: { char *p, *q; if ((*temp == '.' || *temp == ',') && (temp[1] == '\0')) { fprintf(stderr, "%s: %s: prompt syntax error\n" , fnam, strg[cnt].name); return 43; } p = q = temp; while((*q = *p++) != 0) if(*q >= 'a' && *q <= 'z') { *q++ -= 'a' - 1; /* valid metakey */ } else if(!isspace(*q)) { fprintf(stderr, "%s: %s: invalid target metakey\n" , fnam, strg[cnt].name); return 44; } if((unsigned)(q - temp) + 1 != text.length) { fprintf(stderr , "%s: %s: number of metakeys does not match input keys\n" , fnam, strg[cnt].name); return 53; } if(!app(temp)) return 54; state = GETTING_STRING; break; } case GETTING_STRING: if ((*temp == '.' || *temp == ',') && (temp[1] == '\0')) { if (*temp == ',' && text.length && text.text[text.length - 1] == '\n') { /* Cut the text as there is to always be a '\0' at the end of the string */ text.text[--text.length] = '\0'; } state = LOOKING_FOR_START; appMem(vstring, "", 0); /* ensure vstring.text is != NULL */ assert(vstring.text); assert((strg[cnt].flags & 3) == 0 /* New string */ || strg[cnt].vstring); /* Apply the cached text */ if((strg[cnt].flags & 3) == 0 /* New string */ || (strg[cnt].version == version && ((strg[cnt].flags & PERFORM_VALIDATION) == 0 || strcmp(strg[cnt].vstring, vstring.text) == 0))) { /* OK -> replace it */ strg[cnt].version = version; free(strg[cnt].text); strg[cnt].text = text.text; string[cnt].size = text.length + 1; free(strg[cnt].vstring); strg[cnt].vstring = vstring.text; } else { if(strg[cnt].version != version) strg[cnt].flags |= VERSION_MISMATCH; if(strcmp(strg[cnt].vstring, vstring.text) != 0) strg[cnt].flags |= VALIDATION_MISMATCH; /* Failed -> ignore the read text */ free(text.text); free(vstring.text); } text.text = vstring.text = 0; strg[cnt].flags |= in_file; } else { char *p, *q, ch; /* Fetch the '%' format sequences */ q = temp - 1; while((p = strchr(q + 1, '%')) != 0) { if((q = strpbrk(p, "%diouxXfegEGcsnp")) == 0) q = strchr(p, '\0') - 1; //q = p + strlen(p) - 1; if(!appMem(vstring, p, (unsigned)(q - p) + 2)) return 51; } /* Replace backslash escape sequences */ p = q = temp; while((ch = *p++) != 0) { if(ch != '\\') *q++ = ch; else if(!*p) goto noAppendNL; else *q++ = mapBSEscape(&p); } *q++ = '\n'; noAppendNL: if(!appMem(text, temp, (unsigned)(q - temp))) return 82; } break; } } if(ferror(fin)) { pxerror("reading ", fnam); return 34; } fclose(fin); if(state != LOOKING_FOR_START) { fprintf(stderr, "%s: Last string not terminated\n", fnam); return 40; } return 0; }
int loadFile(char *fnam) { unsigned long linenr; char *p; read_state state = LOOKING_FOR_START; FILE *fin; join(fnam, fEXT); if((fin = fopen(fnam, "rt")) == NULL && (fin = fopen(temp, "rt")) == NULL) { pxerror("opening ", fnam); return 33; } linenr = 0; while (fgets(temp, sizeof(temp), fin)) { ++linenr; p = strchr(temp, '\0'); if(p[-1] != '\n') { fprintf(stderr, "Line %lu too long\n", linenr); return 41; } /* Cut trailing control characters */ while (--p >= temp && *p < ' '); p[1] = '\0'; switch (state) { case LOOKING_FOR_START: switch(*temp) { case ':': state = GETTING_STRING; /* Locate the string name */ for(cnt = 0; cnt < maxCnt; ++cnt) if(strcmp(strg[cnt].name, temp + 1) == 0) goto strnameFound; /* string name was not found --> create a new one */ ++maxCnt; strnameFound: free(strg[cnt].name); /* purge assignments */ free(strg[cnt].text); /* of previous run */ if((strg[cnt].name = strdup(temp + 1)) == NULL) { fputs("Out of memory\n", stderr); return 80; } strg[cnt].text = NULL; /* Mark where this entry has been found */ strg[cnt].file |= in_file; break; default: while(p >= temp && isspace(*p)) --p; if(p >= temp) { fprintf(stderr, "Syntax error in line #%lu\n", linenr); return 44; } /** fall through **/ case '\0': case '#': break; } break; case GETTING_STRING: if ((*temp == '.' || *temp == ',') && (temp[1] == '\0')) { if (*temp == '.' && !app("\n")) return 81; state = LOOKING_FOR_START; } else { if(strg[cnt].text && !app("\n")) return 81; if(!app(temp)) return 82; } break; } } if(ferror(fin)) { pxerror("reading ", fnam); return 34; } fclose(fin); if(state == GETTING_STRING) { fprintf(stderr, "%s: Last string not terminated\n", fnam); return 40; } return 0; }
int main(int argc, char **argv) { FILE *dat, *inc; int rc; unsigned long size; string_count_t cnt; /* current string number */ string_size_t lsize; int makeLib = 0; unlink(logfile); if(argv[1] && stricmp(argv[1], "/lib") == 0) { --argc; ++argv; makeLib = 1; } if(argc > 2) { puts("FIXSTRS - Generate STRINGS.DAT and STRINGS.H for a language\n" "Useage: FIXSTRS [/lib] [language]\n" "\tIf no language is specified, only the default strings are read.\n" "\tThe <language>.LNG file must reside in the current directory.\n" "Note: DEFAULT.LNG must be present in the current directory, too."); return 127; } in_file = 1; if((rc = loadFile(fTXT)) != 0) return rc; in_file = 2; if(argc > 1 && (rc = loadFile(argv[1])) != 0) return rc; /* Now all the strings are cached into memory */ if(maxCnt < 2) { fputs("No string definition found.\n", stderr); return 43; } /* Create the LOG file */ if(argc > 1) { /* Only if a local LNG file was specified */ log = NULL; /* No LOG entry til this time */ for(cnt = 0; cnt < maxCnt; ++cnt) { switch(strg[cnt].flags & 3) { case 0: /* Er?? */ fputs("Internal error assigned string has no origin?!\n" , stderr); return 99; case 1: /* DEFAULT.LNG only */ if(!log && (log = fopen(logfile, "wt")) == NULL) { fprintf(stderr, "Cannot create logfile: '%s'\n" , logfile); goto breakLogFile; } fprintf(log, "%s: Missing from local LNG file\n" , strg[cnt].name); break; case 2: /* local.LNG only */ if(!log && (log = fopen(logfile, "wt")) == NULL) { fprintf(stderr, "Cannot create logfile: '%s'\n" , logfile); goto breakLogFile; } fprintf(log, "%s: No such string resource\n" , strg[cnt].name); break; case 3: /* OK */ break; } if(strg[cnt].flags & VERSION_MISMATCH) { if(!log && (log = fopen(logfile, "wt")) == NULL) { fprintf(stderr, "Cannot create logfile: '%s'\n" , logfile); goto breakLogFile; } fprintf(log, "%s: Version mismatch, current is: %u\n" , strg[cnt].name, strg[cnt].version); } if(strg[cnt].flags & VALIDATION_MISMATCH) { if(!log && (log = fopen(logfile, "wt")) == NULL) { fprintf(stderr, "Cannot create logfile: '%s'\n" , logfile); goto breakLogFile; } fprintf(log, "%s: printf() format string mismatch, should be: %s\n" , strg[cnt].name, strg[cnt].vstring); } } if(log) fclose(log); } breakLogFile: /* 1. Adjust the offset and generate the overall size */ for(size = string[0].size, cnt = 1; cnt < maxCnt; ++cnt) { string[cnt].index = string[cnt-1].index + string[cnt-1].size; size += string[cnt].size; } if(size >= 0x10000ul - sizeof(string_index_t) * maxCnt) { fputs("Overall size of strings exceeds 64KB limit\n", stderr); return 44; } /* 2. Open STRINGS.DAT and STRINGS.H and dump control information */ if ((dat = fopen(fDAT,"wb")) == NULL) { perror("creating " fDAT); return 36; } if ((inc = fopen(fH,"wt")) == NULL) { perror("creating " fH); return 37; } puts("FIXSTRS: building STRINGS resource"); fputs("/*\n" " * This file was automatically generated by FIXSTRS.\n" " * Any modifications will be lost next time this tool\n" " * is invoked.\n" " */\n\n", inc); fprintf(inc,"#define STRINGS_ID \"%s%u\"\n" , id, STRING_RESOURCE_MINOR_ID); startResource(dat, RES_ID_STRINGS, STRING_RESOURCE_MINOR_ID); /* Preamble of STRINGS.DAT file */ fprintf(dat, "%s%u", id, STRING_RESOURCE_MINOR_ID); /* fwrite(id, sizeof(id) - 1, 1, dat); *//* file contents ID */ fwrite("\r\n\x1a", 4, 1, dat); /* text file full stop */ fputs("#define STRINGS_ID_TRAILER 4\n", inc); /* 4 additional bytes */ fputs("\n\n", inc); /* delimiter */ /* parameters of strings */ fwrite(&maxCnt, sizeof(maxCnt), 1, dat); /* number of strings */ lsize = (string_size_t)size; fwrite(&lsize, sizeof(lsize), 1, dat); /* total size of string text */ /* string control area */ fwrite(string, sizeof(string[0]), maxCnt, dat); /* append the strings */ for(cnt = 0; cnt < maxCnt; ++cnt) { fwrite(strg[cnt].text, string[cnt].size, 1, dat); if(makeLib) fprintf(inc, "extern const char %s[];\n", strg[cnt].name); fprintf(inc, "#define %-34s 0x%02x /* @ 0x%04x */\n" , strg[cnt].name, cnt, string[cnt].index); } fputs("\n/* END OF FILE */\n", inc); endResource(dat); fflush(dat); if(ferror(dat)) { fputs("Unspecific write error into " fDAT "\n", stderr); return 38; } fflush(inc); if(ferror(inc)) { fputs("Unspecific write error into " fH "\n", stderr); return 39; } fclose(dat); fclose(inc); if(makeLib) { mkdir(stringdir); #define fdmake inc #define ftc101 dat cfilename[-1] = '\\'; strcpy(cfilename, fDMAKEFILE); if((fdmake = fopen(cfile, "wt")) == NULL) { pxerror("creating ", cfile); return 100; } strcpy(cfilename, fTCMAKEFILE); if((ftc101 = fopen(cfile, "wt")) == NULL) { pxerror("creating ", cfile); return 101; } puts("FIXSTRS: building STRINGS library source files"); /********************** prologue */ fputs("\ MAXLINELENGTH := 8192\n\ # Project specific C compiler flags\n\ MYCFLAGS_DBG = -UNDEBUG $(null,$(DEBUG) $(NULL) -DDEBUG=1)\n\ MYCFLAGS_NDBG = -DNDEBUG=1 -UDEBUG\n\ MYCFLAGS = $(null,$(NDEBUG) $(MYCFLAGS_DBG) $(MYCFLAGS_NDBG))\n\ \n\ # Default target\n\ all: $(CFG) strings.lib\n\ \n\ strings.lib .LIBRARY : ", fdmake); /********************* individual files */ for(cnt = 0; cnt < maxCnt; ++cnt) { dumpString(cnt); fprintf(fdmake, "\\\n\t" objfmt, cnt); } for(cnt = 0; cnt < maxCnt - 1; ++cnt) #ifdef __TURBOC__ fprintf(ftc101, "+" objfmt " &\n", cnt); #else fprintf(ftc101, "+" objfmt "\n", cnt); #endif fprintf(ftc101, "+" objfmt " \n", cnt); /********************** epilogue */ fputs("\n\ \n\ .IF $(CFG) != $(NULL)\n\ \n\ CONFIGURATION = $(CONF_BASE)\n\ \n\ .IF $(_COMPTYPE) == BC\n\ CONF_BASE = \\\n\ -f- \\\n\ -I$(INCDIR:s/;/ /:t\";\") \\\n\ -L$(LIBDIR:s/;/ /:t\";\") \\\n\
int loadFile(char *fnam) { unsigned long linenr; char *p; FILE *fin; join(fnam, fEXT); if((fin = fopen(fnam, "rt")) == NULL && (fin = fopen(temp, "rt")) == NULL) { pxerror("opening ", fnam); return 33; } printf("CRITSTRS: load file %s\n", fnam); linenr = 0; while (fgets(temp, sizeof(temp), fin)) { ++linenr; p = strchr(temp, '\0'); if(p[-1] != '\n') { fprintf(stderr, "Line %lu too long\n", linenr); return 41; } /* Cut trailing control characters */ while (--p >= temp && (iscntrl(*p) || isspace(*p))); p[1] = '\0'; switch (*temp) { case ';': case '#': case '\0': /* comment line */ break; case 'S': /* possible help line */ if(isdigit(temp[1])) /* help line */ break; default: /* line */ if((p = strchr(temp, ':')) == NULL) { fprintf(stderr, "Syntax error in line %lu\n", linenr); return 42; } *p = '\0'; if(isdigit(*temp)) { /* error string */ char *q = temp; int nr = 0; do nr = nr * 10 + *q - '0'; while(isdigit(*++q)); if(*q) { fprintf(stderr, "Invalid number in line %lu\n", linenr); return 44; } if(nr < 0 || nr > 255 - STR_ERROR) { fprintf(stderr, "String number too large in line %lu\n" , linenr); return 45; } savetext(strg, STR_ERROR + nr, p + 1); } else { strupr(temp); if(!search(strg, temp, p + 1) && !search(special, temp, p + 1)) { fprintf(stderr, "Unknown string name in line %lu\n" , linenr); return 43; } } } } if(ferror(fin)) { pxerror("reading ", fnam); return 34; } fclose(fin); return 0; }