From: Ian Darwin Date: Fri, 28 Aug 1987 20:29:07 +0000 (+0000) Subject: Add Gilmore's getstr() and printstr(). X-Git-Tag: FILE3_27~429 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d791c554e9398b2f1b25b96ef2059bdc19e998c4;p=file Add Gilmore's getstr() and printstr(). Getstr() includes support for C escapes in strings. --- diff --git a/src/apprentice.c b/src/apprentice.c index 1fea372d..b9db6bf5 100644 --- a/src/apprentice.c +++ b/src/apprentice.c @@ -7,7 +7,8 @@ #include "file.h" #define MAXSTR 500 -#define EATAB {while (isascii(*l) && *l == '\t') ++l;} +#define EATAB {while (isascii(*l) && isspace(*l)) ++l;} + extern char *progname; extern char *magicfile; @@ -17,6 +18,8 @@ extern long strtol(); struct magic magic[MAXMAGIS]; +char *getstr(); + apprentice(fn) char *fn; { @@ -55,12 +58,13 @@ char *l; int *ndx; { int i = 0, nd = *ndx; + int slen; static int warned = 0; struct magic *m; if (nd+1 >= MAXMAGIS){ if (warned++ == 0) - warning("magic tab overflow - increase MAXMAGIS beyond %d in file/apprentice.c\n", MAXMAGIS); + warning("magic table overflow - increase MAXMAGIS beyond %d in file/apprentice.c\n", MAXMAGIS); return 0; } m = &magic[*ndx]; @@ -100,7 +104,7 @@ int *ndx; } EATAB; - if (*l == '>' || *l == '&' || *l == '=') { + if (*l == '>' || *l == '<' || *l == '&' || *l == '=') { m->reln = *l; ++l; } else @@ -110,19 +114,23 @@ int *ndx; /* TODO finish this macro and start using it! */ #define offsetcheck {if (offset > HOWMANY-1) warning("offset too big"); } switch(m->type) { + /* + * Do not remove the casts below. They are vital. + * When later compared with the data, the sign extension must + * have happened. + */ case BYTE: - m->value.l = strtol(l,&l,0); + m->value.l = (char) strtol(l,&l,0); break; case SHORT: - m->value.l = strtol(l,&l,0); + m->value.l = (short) strtol(l,&l,0); break; case LONG: - m->value.l = strtol(l,&l,0); + m->value.l = (long) strtol(l,&l,0); break; case STRING: - /* TODO check return from sscanf (system dependant?) */ - (void) sscanf(l, "%[^\t]", m->value.s); - l += strlen(m->value.s); + l = getstr(l, m->value.s, sizeof(m->value.s), &slen); + m->vallen = slen; break; default: warning("can't happen: m->type=%d\n", m->type); @@ -142,3 +150,176 @@ int *ndx; return 1; } +/* + * Convert a string containing C character escapes. Stop at an unescaped + * space or tab. + * Copy the converted version to "p", returning its length in *slen. + * Return updated scan pointer as function result. + */ +char * +getstr(s, p, plen, slen) +register char *s; +register char *p; +int plen, *slen; +{ + char *origs = s, *origp = p; + char *pmax = p + plen - 1; + register char c; + register int val; + + while((c = *s++) != '\0') { + if (isspace(c)) break; + if (p >= pmax) { + fprintf(stderr, "String too long: %s\n", origs); + break; + } + if(c == '\\') { + switch(c = *s++) { + + case '\0': + goto out; + + default: + *p++ = c; + break; + + case 'n': + *p++ = '\n'; + break; + + case 'r': + *p++ = '\r'; + break; + + case 'b': + *p++ = '\b'; + break; + + case 't': + *p++ = '\t'; + break; + + case 'f': + *p++ = '\f'; + break; + + case 'v': + *p++ = '\v'; + break; + + /* \ and up to 3 octal digits */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + val = c - '0'; + c = *s++; /* try for 2 */ + if(c >= '0' && c <= '7') { + val = (val<<3) | (c - '0'); + c = *s++; /* try for 3 */ + if(c >= '0' && c <= '7') + val = (val<<3) | (c-'0'); + else + --s; + } + else + --s; + *p++ = val; + break; + + /* \x and up to 3 hex digits */ + case 'x': + val = 'x'; /* Default if no digits */ + c = hextoint(*s++); /* Get next char */ + if (c >= 0) { + val = c; + c = hextoint(*s++); + if (c >= 0) { + val = (val << 4) + c; + c = hextoint(*s++); + if (c >= 0) { + val = (val << 4) + c; + } else + --s; + } else + --s; + } else + --s; + *p++ = val; + break; + } + } else + *p++ = c; + } +out: + *p = '\0'; + *slen = p - origp; + return(s); +} + + +/* Single hex char to int; -1 if not a hex char. */ +int +hextoint(c) + char c; +{ + if (!isascii(c)) return -1; + if (isdigit(c)) return c - '0'; + if ((c>='a')&(c<='f')) return c + 10 - 'a'; + if ((c>='A')&(c<='F')) return c + 10 - 'A'; + return -1; +} + + +/* + * Print a string containing C character escapes. + */ +void +showstr(s) +register char *s; +{ + register char c; + + while((c = *s++) != '\0') { + if(c >= 040 && c <= 0176) + putchar(c); + else { + putchar('\\'); + switch (c) { + + case '\n': + putchar('n'); + break; + + case '\r': + putchar('r'); + break; + + case '\b': + putchar('b'); + break; + + case '\t': + putchar('t'); + break; + + case '\f': + putchar('f'); + break; + + case '\v': + putchar('v'); + break; + + default: + printf("%.3o", c & 0377); + break; + } + } + } + putchar('\t'); +}