- const gchash *const *g, *gg = 0;
- size_t sz = strlen(name);
- for (g = ghashtab; *g; g++) {
- if (strncmp(name, (*g)->name, sz) == 0) {
- if ((*g)->name[sz] == 0) {
- gg = *g;
- break;
- } else if (gg)
- return (0);
- else
- gg = *g;
- }
- }
- return (gg);
-}
-
-/* --- @getstring@ --- *
- *
- * Arguments: @FILE *fp@ = stream from which to read
- * @const char *p@ = string to read from instead
- * @dstr *d@ = destination string
- * @unsigned raw@ = raw or cooked read
- *
- * Returns: Zero if OK, nonzero on end-of-file.
- *
- * Use: Reads a filename (or something similar) from a stream.
- */
-
-static int getstring(FILE *fp, const char *p, dstr *d, unsigned raw)
-{
- int ch;
- int q = 0;
-
- /* --- Raw: just read exactly what's written up to a null byte --- */
-
-#define NEXTCH (fp ? getc(fp) : (unsigned char)*p++)
-#define EOFCH (fp ? EOF : 0)
-
- if (raw) {
- if ((ch = NEXTCH) == EOFCH)
- return (EOF);
- for (;;) {
- if (!ch)
- break;
- DPUTC(d, ch);
- if ((ch = NEXTCH) == EOFCH)
- break;
- }
- DPUTZ(d);
- return (0);
- }
-
- /* --- Skip as far as whitespace --- *
- *
- * Also skip past comments.
- */
-
-again:
- ch = NEXTCH;
- while (isspace(ch))
- ch = NEXTCH;
- if (ch == '#') {
- do ch = NEXTCH; while (ch != '\n' && ch != EOFCH);
- goto again;
- }
- if (ch == EOFCH)
- return (EOF);
-
- /* --- If the character is a quote then read a quoted string --- */
-
- switch (ch) {
- case '`':
- ch = '\'';
- case '\'':
- case '\"':
- q = ch;
- ch = NEXTCH;
- break;
- }
-
- /* --- Now read all sorts of interesting things --- */
-
- for (;;) {
-
- /* --- Handle an escaped thing --- */
-
- if (ch == '\\') {
- ch = NEXTCH;
- if (ch == EOFCH)
- break;
- switch (ch) {
- case 'a': ch = '\a'; break;
- case 'b': ch = '\b'; break;
- case 'f': ch = '\f'; break;
- case 'n': ch = '\n'; break;
- case 'r': ch = '\r'; break;
- case 't': ch = '\t'; break;
- case 'v': ch = '\v'; break;
- }
- DPUTC(d, ch);
- ch = NEXTCH;
- continue;
- }
-
- /* --- If it's a quote or some other end marker then stop --- */
-
- if (ch == q)
- break;
- if (!q && isspace(ch))
- break;
-
- /* --- Otherwise contribute and continue --- */
-
- DPUTC(d, ch);
- if ((ch = NEXTCH) == EOFCH)
- break;
- }
-
- /* --- Done --- */
-
- DPUTZ(d);