nl_catd (catopen) (const char *name, int oflag) { _CAT_CATALOG_T *_kitten_catalog = 0; static STRING_T *catfile = 0; static STRING_T *nlspath = 0; size_t pos; /* According to the Posix definition, if name has a '/', the name is the entire path to the file. Expand that to include ':' and '\\' for FreeDOS. */ if (strpbrk (name, ":/\\") != 0) _kitten_catalog = catread (name); else { /* Open the catalog file. */ catfile = DScreate (); nlspath = DScreate (); get_name_from_nlspath (nlspath, (char *) name); while (_kitten_catalog == 0 && DSlength (nlspath) != 0) { pos = DSfind (nlspath, ";", 0, 1); DSassign (catfile, nlspath, 0, pos); if (DSlength (catfile) == 0) DSassigncstr (catfile, (char *) name, NPOS); _kitten_catalog = catread (DScstr (catfile)); DSremove (nlspath, 0, (pos == NPOS) ? NPOS : pos + 1); } DSdestroy (nlspath); DSdestroy (catfile); } /* If we could not find it, return failure. Otherwise, install the catalog and return a cookie. */ return _kitten_catalog ? install_catalog (_kitten_catalog) : (nl_catd) (-1); }
/* NAME catgets - read a program message SYNOPSIS #include <nl_types.h> char *catgets(nl_catd catd, int set_id, int msg_id, const char *s); DESCRIPTION The catgets() function shall attempt to read message msg_id, in set set_id, from the message catalog identified by catd. The catd argument is a message catalog descriptor returned from an earlier call to catopen(). The s argument points to a default message string which shall be returned by catgets() if it cannot retrieve the identified message. The catgets() function need not be reentrant. A function that is not required to be reentrant is not required to be thread-safe. RETURN VALUE If the identified message is retrieved successfully, catgets() shall return a pointer to an internal buffer area containing the null-terminated message string. If the call is unsuccessful for any reason, s shall be returned and errno may be set to indicate the error. ERRORS The catgets() function may fail if: [EBADF] The catd argument is not a valid message catalog descriptor open for reading. [EBADMSG] The message identified by set_id and msg_id in the specified message catalog did not satisfy implementation-defined security criteria. [EINTR] The read operation was terminated due to the receipt of a signal, and no data was transferred. [EINVAL] The message catalog identified by catd is corrupted. [ENOMSG] The message identified by set_id and msg_id is not in the message catalog. */ char *(catgets) (nl_catd catd, int set_id, int msg_id, const char *s) { _CAT_CATALOG_T *cat; static _CAT_MESSAGE_T keymsg = { 0, 0, 0 }; _CAT_MESSAGE_T *msgptr = 0; if (theCatalogues == 0 || _CATCAT_length (theCatalogues) <= catd || (cat = _CATCAT_get_at (theCatalogues, catd))->is_opened == 0) { errno = EBADF; return (char *) s; } keymsg.set_id = set_id; keymsg.msg_id = msg_id; msgptr = bsearch (&keymsg, _CATMSG_base (cat->msgs), _CATMSG_length (cat->msgs), sizeof (_CAT_MESSAGE_T), catmsg_cmp); if (msgptr == 0) { #ifdef ENOMSG errno = ENOMSG; #endif return (char *) s; } return DScstr (msgptr->msg); }
/* 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); }
/* display a block of text */ void display_block (unsigned long first_line, unsigned long last_line, unsigned long current_line, size_t page_size) { unsigned long i; size_t lines_written; for (i = first_line, lines_written = 0; i <= last_line && i < DAS_length (buffer); i++) { printf (G00008, i + 1, i == current_line ? '*' : ' ', DScstr (DAS_get_at (buffer, i))); lines_written++; if (lines_written == page_size && i != last_line) { read_line (G00009); lines_written = 0; } } }
/* 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); }
/* write X number of lines to a file */ void write_file (unsigned long lines, char *filename) { FILE *f; size_t i; make_bakfile (filename); if ((f = fopen (filename, "w"))) { i = DAS_length (buffer); if (lines >= i) lines = i; for (i = 0; i < lines; i++) { fputs ((const char *) DScstr (DAS_get_at (buffer, i)), f); fputc ('\n', f); } fclose (f); printf ((i == 1) ? G00006 : G00007, filename, (unsigned long) i); } }
/* search_buffer - search a buffer for a string */ unsigned long search_buffer (unsigned long current_line, unsigned long line1, unsigned long line2, int verify, char *s) { unsigned long line; STRING_T *ds; int q = 0; char *yn; size_t numlines = DAS_length (buffer); if (line1 > numlines || line2 > numlines) { puts (G00003); return current_line; } while (isspace ((unsigned char) *s)) s++; if (*s == '\'' || *s == '\"') q = *s++; ds = translate_string (s, q); if (DSlength (ds) != 0) for (line = line1; line <= line2; line++) { if (DSfind (DAS_get_at (buffer, (size_t) line), DScstr (ds), 0, DSlength (ds)) != NPOS) { display_block (line, line, line, 1); if (verify) { yn = read_line (G00002); if (*yn == 0 || strchr (YES, *yn) != 0) return line + 1; } else return line + 1; } } puts (G00011); return current_line; }
/* replace_buffer - search the buffer for a string, then replace it with another string. */ unsigned long replace_buffer (unsigned long current_line, unsigned long line1, unsigned long line2, int verify, char *s) { unsigned long line; STRING_T *ds, *ds1, *dc; int q = 0; char *yn; size_t origpos; while (isspace ((unsigned char) *s)) s++; if (*s == '\'' || *s == '\"') q = *s++; else q = ','; ds = DScreate (); DSassign (ds, translate_string (s, q), 0, NPOS); /* pick off second string */ while (*s != q && *s) s += (*s == '\\' ? 2 : 1); while (*s != ',') s++; s++; while (isspace ((unsigned char) *s)) s++; if (*s == '\'' || *s == '\"') q = *s++; else q = 0; ds1 = DScreate (); DSassign (ds1, translate_string (s, q), 0, NPOS); if (DSlength (ds) != 0 && DScompare (ds, ds1, 0, NPOS) != 0) for (line = line1; line <= line2; line++) { origpos = 0; while ((origpos = DSfind (DAS_get_at (buffer, (size_t) line), DScstr (ds), origpos, DSlength (ds))) != NPOS) { dc = DScreate (); DSassign (dc, DAS_get_at (buffer, line), 0, NPOS); DSreplace (dc, origpos, DSlength (ds), ds1, 0, NPOS); printf (G00012, line + 1, DScstr (dc)); if (verify) yn = read_line (G00002); if (!verify || (*yn == 0 || strchr (YES, *yn) != 0)) { current_line = line + 1; origpos += DSlength (ds1); DAS_put_at (buffer, line, dc); } else origpos++; DSdestroy (dc); } } DSdestroy (ds); DSdestroy (ds1); return current_line; }