int chrtoi(register const char *s) { register int c; register int n; register int x; char *p; c = 0; for (n = 0; n < sizeof(int) * CHAR_BIT; n += CHAR_BIT) { switch (x = *((unsigned char *) s++)) { case '\\': x = chresc(s - 1, &p); s = (const char *) p; break; case 0: return (c); } c = (c << CHAR_BIT) | x; } return (c); }
int stresc(register char *s) { register char *t; register int c; char *b; char *p; b = t = s; for (;;) { switch (c = *s++) { case '\\': c = chresc(s - 1, &p); s = p; break; case 0: *t = 0; return (t - b); } *t++ = c; } }
size_t stresc(char *out, size_t n, const char *in) { const char *ptr = in; char ch, *bptr = out, buff[3]; size_t written = 0; while ((ch = *ptr++)) { if ((written += (chresc(buff, ch, '"') - buff)) <= n) { *bptr++ = buff[0]; if ((ch = buff[1])) { *bptr = ch; bptr++; } } } if (bptr) { while (written < n) { *bptr = '\0'; bptr++; written++; } } return written; }
int main(int argc, char** argv) { register Mc_t* mc; register char* s; register char* t; register int c; register int q; register int i; int num; char* b; char* e; char* catfile; char* msgfile; Sfio_t* sp; Sfio_t* mp; Sfio_t* tp; Xl_t* px; Xl_t* bp; Xl_t* xp = 0; int format = 0; int list = 0; int set = 0; NoP(argc); error_info.id = "msggen"; for (;;) { switch (optget(argv, usage)) { case 'f': format = list = 1; continue; case 'l': list = 1; continue; case 's': set = 1; continue; case '?': error(ERROR_USAGE|4, "%s", opt_info.arg); continue; case ':': error(2, "%s", opt_info.arg); continue; } break; } argv += opt_info.index; if (error_info.errors || !(catfile = *argv++)) error(ERROR_USAGE|4, "%s", optusage(NiL)); /* * set and list only need catfile */ if (set) { sfprintf(sfstdout, "%d\n", mcindex(catfile, NiL, NiL, NiL)); return error_info.errors != 0; } else if (list) { if (!(sp = sfopen(NiL, catfile, "r"))) error(ERROR_SYSTEM|3, "%s: cannot read catalog", catfile); if (!(mc = mcopen(sp))) error(ERROR_SYSTEM|3, "%s: catalog content error", catfile); sfclose(sp); if (format) { for (set = 1; set <= mc->num; set++) if (mc->set[set].num) { sfprintf(sfstdout, "$set %d\n", set); for (num = 1; num <= mc->set[set].num; num++) if (s = mc->set[set].msg[num]) sfprintf(sfstdout, "%d \"%s\"\n", num, fmtfmt(s)); } } else { if (*mc->translation) { ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$translation "); sfprintf(sfstdout, "%s", mc->translation); ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "\n"); } ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$quote \"\n"); for (set = 1; set <= mc->num; set++) if (mc->set[set].num) { ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$set %d\n", set); for (num = 1; num <= mc->set[set].num; num++) if (s = mc->set[set].msg[num]) { ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "%d \"", num); while (c = *s++) { /*INDENT...*/ switch (c) { case 0x22: /* " */ case 0x5C: /* \ */ sfputc(sfstdout, 0x5C); break; case 0x07: /* \a */ c = 0x61; sfputc(sfstdout, 0x5C); break; case 0x08: /* \b */ c = 0x62; sfputc(sfstdout, 0x5C); break; case 0x0A: /* \n */ c = 0x6E; sfputc(sfstdout, 0x5C); break; case 0x0B: /* \v */ c = 0x76; sfputc(sfstdout, 0x5C); break; case 0x0C: /* \f */ c = 0x66; sfputc(sfstdout, 0x5C); break; case 0x0D: /* \r */ c = 0x72; sfputc(sfstdout, 0x5C); break; } /*...UNDENT*/ sfputc(sfstdout, c); } ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "\"\n"); } } } mcclose(mc); return error_info.errors != 0; } else if (!(msgfile = *argv++) || *argv) error(3, "exactly one message file must be specified"); /* * open the files and handles */ if (!(tp = sfstropen())) error(ERROR_SYSTEM|3, "out of space [string stream]"); if (!(mp = sfopen(NiL, msgfile, "r"))) error(ERROR_SYSTEM|3, "%s: cannot read message file", msgfile); sp = sfopen(NiL, catfile, "r"); if (!(mc = mcopen(sp))) error(ERROR_SYSTEM|3, "%s: catalog content error", catfile); if (sp) sfclose(sp); xp = translation(xp, mc->translation); /* * read the message file */ q = 0; set = 1; error_info.file = msgfile; while (s = sfgetr(mp, '\n', 1)) { error_info.line++; if (!*s) continue; if (*s == '$') { if (!*++s || isspace(*s)) continue; for (t = s; *s && !isspace(*s); s++); if (*s) *s++ = 0; if (streq(t, "delset")) { while (isspace(*s)) s++; num = (int)strtol(s, NiL, 0); if (num < mc->num && mc->set[num].num) for (i = 1; i <= mc->set[num].num; i++) mcput(mc, num, i, NiL); } else if (streq(t, "quote")) q = *s ? *s : 0; else if (streq(t, "set")) { while (isspace(*s)) s++; num = (int)strtol(s, &e, 0); if (e != s) set = num; else error(2, "set number expected"); } else if (streq(t, "translation")) xp = translation(xp, s); } else { t = s + sfvalue(mp); num = (int)strtol(s, &e, 0); if (e != s) { s = e; if (!*s) { if (mcput(mc, set, num, NiL)) error(2, "(%d,%d): cannot delete message", set, num); } else if (isspace(*s++)) { if (t > (s + 1) && *(t -= 2) == '\\') { sfwrite(tp, s, t - s); while (s = sfgetr(mp, '\n', 0)) { error_info.line++; t = s + sfvalue(mp); if (t <= (s + 1) || *(t -= 2) != '\\') break; sfwrite(tp, s, t - s); } if (!(s = sfstruse(tp))) error(ERROR_SYSTEM|3, "out of space"); } if (q) { if (*s++ != q) { error(2, "(%d,%d): %c quote expected", set, num, q); continue; } b = t = s; while (c = *s++) { if (c == '\\') { c = chresc(s - 1, &e); s = e; if (c) *t++ = c; else error(1, "nul character ignored"); } else if (c == q) break; else *t++ = c; } if (*s) { error(2, "(%d,%d): characters after quote not expected", set, num); continue; } *t = 0; s = b; } if (mcput(mc, set, num, s)) error(2, "(%d,%d): cannot add message", set, num); } else error(2, "message text expected"); } else error(2, "message number expected"); } } error_info.file = 0; error_info.line = 0; /* * fix up the translation record */ if (xp) { t = ""; for (;;) { for (bp = 0, px = xp; px; px = px->next) if (px->date && (!bp || strcoll(bp->date, px->date) < 0)) bp = px; if (!bp) break; sfprintf(tp, "%s%s %s", t, bp->name, bp->date); t = ", "; bp->date = 0; } if (!(mc->translation = sfstruse(tp))) error(ERROR_SYSTEM|3, "out of space"); } /* * dump the catalog to a local temporary * rename if no errors */ if (!(s = pathtemp(NiL, 0, "", error_info.id, NiL)) || !(sp = sfopen(NiL, s, "w"))) error(ERROR_SYSTEM|3, "%s: cannot write catalog file", catfile); if (mcdump(mc, sp) || mcclose(mc) || sfclose(sp)) { remove(s); error(ERROR_SYSTEM|3, "%s: temporary catalog file write error", s); } remove(catfile); if (rename(s, catfile)) error(ERROR_SYSTEM|3, "%s: cannot rename from temporary catalog file %s", catfile, s); return error_info.errors != 0; }
Recfmt_t recstr(register const char* s, char** e) { char* t; int n; long v; int a[6]; while (*s == ' ' || *s == '\t' || *s == ',') s++; switch (*s) { case 'd': case 'D': if (!*s) n = '\n'; else { if (*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) n = (int)strtol(s, &t, 0); else n = chresc(s, &t); s = (const char*)t; } if (e) *e = (char*)s; return REC_D_TYPE(n); case 'f': case 'F': while (*++s == ' ' || *s == '\t' || *s == ','); /*FALLTHROUGH*/ case '+': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = strton(s, &t, NiL, 0); if (n > 0 && t > (char*)s) { if (e) *e = t; return REC_F_TYPE(n); } break; case 'm': case 'M': while (*++s == ' ' || *s == '\t' || *s == ','); for (t = (char*)s; *t && *t != ' ' && *t != '\t' && *t != ','; t++); if ((t - s) == 4) { if (strneq(s, "data", 4)) { if (e) *e = t; return REC_M_TYPE(REC_M_data); } else if (strneq(s, "path", 4)) { if (e) *e = t; return REC_M_TYPE(REC_M_path); } } /* * TBD: look up name in method libraries * and assign an integer index */ break; case 'u': case 'U': while (*++s == ' ' || *s == '\t' || *s == ','); n = strtol(s, &t, 0); if (n < 0 || n > 15 || *t++ != '.') break; v = strtol(t, &t, 0); if (*t) break; if (e) *e = t; return REC_U_TYPE(n, v); case 'v': case 'V': a[0] = 0; a[1] = 4; a[2] = 0; a[3] = 2; a[4] = 0; a[5] = 1; n = 0; for (;;) { switch (*++s) { case 0: break; case 'm': case 'M': n = 0; continue; case 'h': case 'H': n = 1; continue; case 'o': case 'O': n = 2; continue; case 'z': case 'Z': n = 3; continue; case 'b': case 'B': n = 4; a[n++] = 0; continue; case 'l': case 'L': n = 4; a[n++] = 1; continue; case 'n': case 'N': n = 0; a[5] = 0; continue; case 'i': case 'I': n = 0; a[5] = 1; continue; case ' ': case '\t': case ',': case '-': case '+': continue; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': v = 0; a[n++] = strtol(s, &t, 0); s = (const char*)t - 1; continue; } break; } if (e) *e = (char*)s; if (a[3] > (a[1] - a[2])) a[3] = a[1] - a[2]; return REC_V_RECORD(REC_V_TYPE(a[1], a[2], a[3], a[4], a[5]), a[0]); case '%': if (e) *e = (char*)s + 1; return REC_M_TYPE(REC_M_path); case '-': case '?': if (e) *e = (char*)s + 1; return REC_M_TYPE(REC_M_data); } if (e) *e = (char*)s; return REC_N_TYPE(); }