]> granicus.if.org Git - file/commitdiff
Add Gilmore's getstr() and printstr().
authorIan Darwin <ian@darwinsys.com>
Fri, 28 Aug 1987 20:29:07 +0000 (20:29 +0000)
committerIan Darwin <ian@darwinsys.com>
Fri, 28 Aug 1987 20:29:07 +0000 (20:29 +0000)
Getstr() includes support for C escapes in strings.

src/apprentice.c

index 1fea372d6a089d48fafedd008d8a63ef574a48ca..b9db6bf5c0c574090aac31b84ee4ccf520aa2398 100644 (file)
@@ -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');
+}