diff options
Diffstat (limited to 'lib/libmytinfo/findterm.c')
-rw-r--r-- | lib/libmytinfo/findterm.c | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/lib/libmytinfo/findterm.c b/lib/libmytinfo/findterm.c new file mode 100644 index 0000000..1fe5a9b --- /dev/null +++ b/lib/libmytinfo/findterm.c @@ -0,0 +1,286 @@ +/* findterm.c + * + * By Ross Ridge + * Public Domain + * 92/02/01 07:29:56 + * + */ + +#include "defs.h" + +#include <ctype.h> +#include <fcntl.h> +#ifdef USE_STDDEF +#include <sys/types.h> +#endif +#include <sys/stat.h> +#ifdef __FreeBSD__ +#include <unistd.h> +#endif + +#ifdef USE_SCCS_IDS +static const char SCCSid[] = "@(#) mytinfo findterm.c 3.2 92/02/01 public domain, By Ross Ridge"; +#endif +static int linecnt; + +static int +getln(f, buf, len) +FILE *f; +register char *buf; +int len; { + register int c, i = 0; + + while((c = getc(f)) == '#') { + linecnt++; + while((c = getc(f)) != '\n') + if (c == EOF) + return -1; + } + + while(c != '\n') { + if (c == EOF) + return -1; + if (i < len) { + i++; + *buf++ = c; + } + c = getc(f); + } + + while(isspace(*(buf-1))) { + buf--; + i--; + } + + *buf = '\0'; + return i; +} + +static int +_findterm2(name, file, buf) +char *name, *buf; +char *file; { + char line[MAX_LINE]; + FILE *f; + register char *sp, *dp; + int c; + int l; + int cont; + int fd; + struct stat st; + + linecnt = 0; + +#ifdef DEBUG + printf("open: %s\n", file); +#endif + fd = open(file, O_RDONLY); + if (fd == -1) + return -1; + if (fstat(fd, &st) == -1) { + close(fd); + return -1; + } + if ((st.st_mode & 0170000) == 0040000) { + sprintf(buf, "%s/%c/%s", file, name[0], name); + close(fd); + fd = open(buf, O_RDONLY); + if (fd == -1) + return -1; + if (read(fd, buf, MAX_BUF) < 12 + || buf[0] != 032 || buf[1] != 1) { + close(fd); + return -1; + } + close(fd); + return 3; + } + f = fdopen(fd, "r"); + if (f == NULL) { + close(fd); + return -1; + } + + while ((l = getln(f, buf, MAX_LINE)) != -1) { + linecnt++; + if (!isspace(buf[0]) && l != 0) { + sp = buf + l - 1; + cont = 0; + switch(*sp) { + case '\\': + cont = 1; + *sp = '\0'; + /* FALLTHROUGH */ + case ':': + sp = buf; + dp = line; + while (*sp != ':') { + if (*sp == '\0' && cont && + (l = getln(f, buf, MAX_LINE)) + != -1) { + linecnt++; + sp = buf; + if (l > 0 && buf[l-1] == '\\') + cont = 1; + else + cont = 0; + continue; + } + if (*sp == '\0') { +#ifdef DEBUG + printf("bad line (%d)\n", + linecnt); + fclose(f); + return -2; +#else + goto err; +#endif + } + *dp++ = *sp++; + } + *dp = '\0'; + if (!_tmatch(line, name)) + break; + if (!cont) { + fclose(f); + return 1; + } + l = strlen(buf); + dp = buf + l; + while((c = getc(f)) != EOF && l < MAX_BUF) { + if (c == '\n') + break; + if (c == '\\') { + c = getc(f); + if (c == EOF) + break; + if (c == '\n') { + c = getc(f); + if (c == EOF) + break; + if (c == '#') { + while((c = getc(f)) != EOF && c != '\n'); + if (c == EOF) + break; + continue; + } + *dp++ = c; + continue; + } + *dp++ = '\\'; + *dp++ = c; + continue; + } + *dp++ = c; + } + *dp = '\0'; + fclose(f); + return 1; + case ',': + sp = buf; + dp = line; + while(*sp != ',') + *dp++ = *sp++; + *dp = '\0'; + if (!_tmatch(line, name)) + break; + dp = buf + l; + while ((c = getc(f)) != EOF && l < MAX_BUF) { + if (c == '\n') { + c = getc(f); + if (isspace(c)) + continue; + if (c == '\n') { + ungetc(c, f); + continue; + } + if (c == '#') { + while((c = getc(f)) != EOF) + if (c == '\n') + break; + if (c == EOF) + break; + ungetc(c, f); + continue; + } + break; + } + *dp++ = c; + l++; + } + *dp = '\0'; + fclose(f); + return 2; + default: + err: +#ifdef DEBUG + printf("strange line (%d)\n", linecnt); +#endif + break; + } + } + } + fclose(f); + return 0; +} + +int +_findterm(name, path, buf) +char *name; +struct term_path *path; +char *buf; { + register char *s, *d; + int r = 0; + while(path->file != NULL) { + switch(path->type) { + case 0: + r = _findterm2(name, path->file, buf); + break; + case 1: + if (path->file[0] == '/') { + r = _findterm2(name, path->file, buf); + } else { + s = path->file; + d = buf; + while(*s != '\0' && *s != ':') + *d++ = *s++; + *d = '\0'; + if (_tmatch(buf, name)) { + while(*s != '\0') + *d++ = *s++; + return 1; + } + r = 0; + } + break; + case 2: + if (path->file[0] == '/') { + r = _findterm2(name, path->file, buf); + } else { + s = path->file; + d = buf; + while(*s != '\0' && *s != ',') + *d++ = *s++; + *d = '\0'; + if (_tmatch(buf, name)) { + while(*s != '\0') + *d++ = *s++; + return 2; + } + r = 0; + } + break; + default: + r = 0; + break; + } + if (r == 1 || r == 2 || r == 3) { +#ifdef DEBUG + printf("found in %s\n", path->file); +#endif + break; + } + path++; + } + return r; +} |