/* read a line from stdin */ char * read_line (char *prompt) { static STRING_T *ds = 0; int c; #ifdef SHIFT_JIS size_t ds_length = 0; #endif if (ds == 0) ds = DScreate (); DSresize (ds, 0, 0); fputs (prompt, stdout); fflush (stdout); #ifndef SHIFT_JIS /* Normal terminal input. Assumes that I don't have to handle control characters here. */ while ((c = getchar ()) != EOF && c != '\n') DSappendchar (ds, c, 1); #else /* SHIFT_JIS */ /* Rolling our own getchar loop here. The thing to watch out for is that a backspace has to destroy BOTH characters of a Shift-JIS code and that a carriage return is equivalent to a newline. */ do { while (!kbhit_f ()) ; /* key wait */ c = getch (); if (c == '\r') c = '\n'; if (c == '\b') { /* handle backspace */ ds_length = DSlength (ds); if (ds_length >= 2 && iskanji (DSgetat (ds, ds_length - 2))) { DSresize (ds, ds_length - 2, 0); fputs ("\b \b\b \b", stdout); } else if (ds_length > 0) { DSresize (ds, ds_length - 1, 0); fputs ("\b \b", stdout); } } else { /* normal character */ putchar (c); DSappendchar (ds, c, 1); } fflush (stdout); } while (c != EOF && c != '\n'); #endif /* SHIFT_JIS */ return DScstr (ds); }
/* transfer_file - merges the contents of a file on disk with a file in memory */ void transfer_file (unsigned long line, char *filename) { STRING_T *s = DScreate (); FILE *f; int c; unsigned long init_line = line; if (line > DAS_length (buffer)) { puts (G00003); return; } if ((f = fopen (filename, "r"))) { while ((c = getc (f)) != EOF) { if (c == '\n') { /* add s to buffer and reset s */ DAS_insert (buffer, line++, s, 1, 1); DSresize (s, 0, '\0'); } else DSappendchar (s, c, 1); } fclose (f); } printf ((line - init_line == 1) ? G00004 : G00005, filename, line - init_line); DSdestroy (s); }
/* make_bakfile - make a backup file */ static void make_bakfile (char *filename) { STRING_T *s = 0; size_t pos, dotpos; static char dot[2] = { '.', '\0' }; /* to foil cstrings */ static char bak[5] = { '.', 'b', 'a', 'k', '\0' }; if (!file_exists (filename)) return; s = DScreate (); DSassigncstr (s, filename, NPOS); pos = DSfind_last_of (s, FILENAME_DELIMITERS, NPOS, NPOS); dotpos = DSfind (s, dot, pos + 1, NPOS); if (dotpos != NPOS) DSresize (s, dotpos, 0); DSappendcstr (s, bak, NPOS); rename (filename, DScstr (s)); DSdestroy (s); }
/* translate_string - translate a string with escapes into regular string */ static STRING_T * translate_string (char *s, int tc) { static STRING_T *r = 0; /* The following are arrays of characters to foil cstrings, as they are not to be translated. */ static char escs[] = { 'a', 'b', 'e', 'f', 't', 'v', '\\', '\'', '\"', '.' }; static char xlat[] = { '\a', '\b', '\033', '\f', '\t', '\v', '\\', '\'', '\"', '.' }; static char xdigs[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; char *p; int x; #ifdef SHIFT_JIS char *org = s; /* The original place in the string. */ int iskj; /* The iskanji() return value. */ #endif /* SHIFT_JIS */ if (r == 0) r = DScreate (); DSresize (r, 0, 0); while (*s && *s != tc) { #ifndef SHIFT_JIS if (*s == '\\') #else /* SHIFT_JIS */ iskj = (org < s) && iskanji (s[-1]); if ((*s == '\\') && !(iskj)) #endif /* SHIFT_JIS */ { /* found an escape */ s++; if ((p = strchr (escs, *s)) != 0) DSappendchar (r, xlat[p - escs], 1); else if (*s == 'x') { /* handle hex digits */ s++; x = 0; while (isxdigit ((unsigned char) *s)) { p = strchr (xdigs, tolower ((unsigned char) *s)); x <<= 4; x |= (p - xdigs); s++; } s--; DSappendchar (r, (x & 255), 1); } else if (*s == 'd') { /* handle decimal digits */ s++; x = 0; while (isdigit ((unsigned char) *s)) x = (x * 10) + (*s++ - '0'); s--; DSappendchar (r, (x & 255), 1); } else if (*s >= '0' && *s <= '7') { /* handle octal digits */ x = 0; while (isdigit ((unsigned char) *s)) { x <<= 3; x |= (*s - '0'); s++; } s--; DSappendchar (r, (x & 255), 1); } else if (*s == '^') { /* control character */ s++; x = toupper ((unsigned char) *s) ^ 64; DSappendchar (r, x, 1); } } else DSappendchar (r, *s, 1); s++; } return r; }
static STRING_T * get_name_from_nlspath (STRING_T * r, char *name) { char *nlspath = 0; char *lang = 0; size_t pos, oldpos, iter; STRING_T *language = 0, *territory = 0, *codeset = 0, *s = 0; nlspath = getenv ("NLSPATH"); lang = get_language (); DSresize (r, 0, 0); if (nlspath == 0) { DSassigncstr (r, name, NPOS); return r; } DSassigncstr (r, nlspath, NPOS); /* set language, territory, codeset values */ if (*lang != 0) { s = DScreate (); language = DScreate (); territory = DScreate (); codeset = DScreate (); DSassigncstr (s, lang, NPOS); for (iter = 3, oldpos = pos = 0; iter != 0; oldpos = pos, --iter, pos = DSfind (s, "@._", ++pos, iter)) { /* assign values */ if (oldpos == 0) DSassign (language, s, 0, pos); else { switch (DSget_at (s, oldpos)) { case '_': /* territory */ DSassign (territory, s, oldpos + 1, pos - oldpos - 1); break; case '.': /* codeset */ DSassign (codeset, s, oldpos + 1, pos - oldpos - 1); break; default: /*modifier? */ break; } if (pos == NPOS) break; } } } for (pos = 0; (pos = DSfind (r, "%", pos, 1)) != NPOS; ++pos) { switch (DSget_at (r, pos + 1)) { case 'N': /* name */ DSreplacecstr (r, pos, 2, name, NPOS); pos += strlen (name) - 1; break; case 'L': /* language */ DSreplacecstr (r, pos, 2, lang, NPOS); pos += strlen (lang) - 1; break; case 'l': /* language element from %L */ DSreplace (r, pos, 2, language, 0, NPOS); pos += DSlength (language) - 1; break; case 't': /* territory element from %L */ if (territory != 0) { DSreplace (r, pos, 2, territory, 0, NPOS); pos += DSlength (territory) - 1; } break; case 'c': /* codeset element from %L */ if (codeset != 0) { DSreplace (r, pos, 2, codeset, 0, NPOS); pos += DSlength (codeset) - 1; } break; case '%': /* percent sign */ DSremove (r, pos, 1); break; } } if (s != 0) DSdestroy (s); if (language != 0) DSdestroy (language); if (territory != 0) DSdestroy (territory); if (codeset != 0) DSdestroy (codeset); return r; }
/* catread - read a catalogue file */ static _CAT_CATALOG_T * catread (const char *name) { FILE *f; STRING_T *s = DScreate (), *t = DScreate (); _CAT_CATALOG_T *cat = 0; size_t z; _CAT_MESSAGE_T catmsg = { 0, 0, 0 }; int c; /* Open the catfile */ f = fopen (name, "r"); if (f == 0) return 0; /* could not open file */ setvbuf (f, 0, _IOFBF, 16384); while (DSlength (s = append_from_file (f, s)) > 0) { DSresize (s, DSlength (s) - 1, 0); /* We have a full line */ if (DSlength (s) > 0) { z = DSfind_first_not_of (s, " \t\f\v\r", 0, NPOS); DSremove (s, 0, z); z = DSfind_last_not_of (s, " \t\f\v\r", NPOS, NPOS); DSresize (s, z + 1, 0); } if (DSlength (s) > 0 && DSget_at (s, DSlength (s) - 1) == '\\') { /* continuation */ DSresize (s, DSlength (s) - 1, 0); } else { if (DSlength (s) > 0 && isdigit (DSget_at (s, 0))) { /* if it starts with a digit, assume it's a catalog line */ for (z = 0, catmsg.set_id = 0; isdigit (c = DSget_at (s, z)); catmsg.set_id = catmsg.set_id * 10 + (c - '0'), z++); z++; for (catmsg.msg_id = 0; isdigit (c = DSget_at (s, z)); catmsg.msg_id = catmsg.msg_id * 10 + (c - '0'), z++); z++; DSremove (s, 0, z); transform_string (t, s); if (catmsg.msg == 0) catmsg.msg = DScreate (); DSassign (catmsg.msg, t, 0, NPOS); if (cat == 0) { cat = malloc (sizeof (_CAT_CATALOG_T)); if (cat == 0) Nomemory (); cat->is_opened = 0; cat->msgs = _CATMSG_create (); } _CATMSG_append (cat->msgs, &catmsg, 1, 0); } DSresize (s, 0, 0); } } fclose (f); qsort (_CATMSG_base (cat->msgs), _CATMSG_length (cat->msgs), sizeof (_CAT_MESSAGE_T), catmsg_cmp); return cat; }
static void transform_string (STRING_T * t, STRING_T * s) { int c, state = 0, accum = 0; size_t ip = 0, i; static int fsm[] = { 0, '\\', FSM_SUPPRESS, 1, 0, FSM_ANY, FSM_OUTPUT, 0, 1, 'b', '\b', 0, 1, 'e', '\033', 0, 1, 'f', '\f', 0, 1, 'n', '\n', 0, 1, 'r', '\r', 0, 1, 't', '\t', 0, 1, 'v', '\v', 0, 1, '\\', '\\', 0, 1, 'd', FSM_SUPPRESS, 2, 1, FSM_ODIGIT, FSM_BASE8, 3, 1, 'x', FSM_SUPPRESS, 4, 1, FSM_ANY, FSM_OUTPUT, 0, 2, FSM_DIGIT, FSM_BASE10, 21, 2, FSM_ANY, FSM_RETAIN, 0, 3, FSM_ODIGIT, FSM_BASE8, 31, 3, FSM_ANY, FSM_RETAIN, 0, 4, FSM_XDIGIT, FSM_BASE16, 4, 4, FSM_ANY, FSM_RETAIN, 0, 21, FSM_DIGIT, FSM_BASE10, 22, 21, FSM_ANY, FSM_RETAIN, 0, 22, FSM_DIGIT, FSM_BASE10_OUTPUT, 0, 22, FSM_ANY, FSM_RETAIN, 0, 31, FSM_ODIGIT, FSM_BASE8_OUTPUT, 0, 31, FSM_ANY, FSM_RETAIN, 0, -1, -1, -1, -1 }; static char hexits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', '\0' }; DSresize (t, 0, 0); while (ip < DSlength (s) && (c = DSget_at (s, ip)) != '\0') { for (i = 0; !(fsm[i] == state && (fsm[i + 1] == c || fsm[i + 1] == FSM_ANY || (fsm[i + 1] == FSM_DIGIT && isdigit (c)) || (fsm[i + 1] == FSM_ODIGIT && strchr ("01234567", c) != 0) || (fsm[i + 1] == FSM_XDIGIT && isxdigit (c)))); i += 4); switch (fsm[i + 2]) { case FSM_OUTPUT: DSappendchar (t, c, 1); ip++; break; case FSM_SUPPRESS: accum = 0; ip++; break; case FSM_BASE10: accum = (accum * 10) + (c - '0'); ip++; break; case FSM_BASE8: accum = (accum << 3) + (c - '0'); ip++; break; case FSM_BASE16: accum = (accum << 4) + (strchr (hexits, tolower (c)) - hexits); ip++; break; case FSM_BASE10_OUTPUT: accum = (accum * 10) + (c - '0'); DSappendchar (t, accum, 1); accum = 0; ip++; break; case FSM_BASE8_OUTPUT: accum = (accum << 3) + (c - '0'); DSappendchar (t, accum, 1); accum = 0; ip++; break; case FSM_RETAIN: DSappendchar (t, accum, 1); accum = 0; break; default: DSappendchar (t, fsm[i + 2], 1); ip++; break; } state = fsm[i + 3]; } }