Part of Guy Harris' Jan-93 rewrite, including:
authorIan Darwin <ian@darwinsys.com>
Fri, 19 Feb 1993 14:22:48 +0000 (14:22 +0000)
committerIan Darwin <ian@darwinsys.com>
Fri, 19 Feb 1993 14:22:48 +0000 (14:22 +0000)
Add in support for multiple levels of continuation.

Add in support for "beshort", "belong", "bedate", "leshort",
"lelong", and "ledate" types.

Also, make old-style "not set"ting - "0 byte ^0x80 statically
linked", meaning "this line matches if any of the bits in the
value *aren't* set in the number from the file" - work.

src/softmagic.c

index df0efb3e1093e49cfecef1720993e0708f5cc83c..4271ba941d224ff291f18ef26ff3cae4b4e78118 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef        lint
 static char *moduleid = 
-       "@(#)$Id: softmagic.c,v 1.16 1992/09/14 14:17:02 ian Exp $";
+       "@(#)$Id: softmagic.c,v 1.17 1993/02/19 14:22:48 ian Exp $";
 #endif /* lint */
 
 static int match       __P((unsigned char *));
@@ -59,35 +59,100 @@ int nbytes;
 }
 
 /*
- * go through the whole list, stopping if you find a match.
- * Be sure to process every continuation of this match.
+ * Go through the whole list, stopping if you find a match.  Process all
+ * the continuations of that match before returning.
+ *
+ * We support multi-level continuations:
+ *
+ *     At any time when processing a successful top-level match, there is a
+ *     current continuation level; it represents the level of the last
+ *     successfully matched continuation.
+ *
+ *     Continuations above that level are skipped as, if we see one, it
+ *     means that the continuation that controls them - i.e, the
+ *     lower-level continuation preceding them - failed to match.
+ *
+ *     Continuations below that level are processed as, if we see one,
+ *     it means we've finished processing or skipping higher-level
+ *     continuations under the control of a successful or unsuccessful
+ *     lower-level continuation, and are now seeing the next lower-level
+ *     continuation and should process it.  The current continuation
+ *     level reverts to the level of the one we're seeing.
+ *
+ *     Continuations at the current level are processed as, if we see
+ *     one, there's no lower-level continuation that may have failed.
+ *
+ *     If a continuation matches, we bump the current continuation level
+ *     so that higher-level continuations are processed.
  */
 static int
 match(s)
 unsigned char  *s;
 {
        int magindex = 0;
+       int cont_level = 0;
+       int need_separator = 0;
+
        while (magindex < nmagic) {
                /* if main entry matches, print it... */
                if (mcheck(s, &magic[magindex])) {
                        mprint(&magic[magindex],s);
+                       /*
+                        * If we printed something, we'll need to print
+                        * a blank before we print something else.
+                        */
+                       if (magic[magindex].desc[0])
+                               need_separator = 1;
                        /* and any continuations that match */
-                       while (magic[magindex+1].flag &&
+                       cont_level++;
+                       while (magic[magindex+1].cont_level != 0 &&
                                magindex < nmagic) {
                                ++magindex;
-                               if (mcheck(s, &magic[magindex])) {
-                                       /* space if previous printed */
-                                       if (magic[magindex-1].desc[0]
-                                          && (magic[magindex].nospflag == 0)
-                                          )
-                                               (void) putchar(' ');
-                                       mprint(&magic[magindex],s);
+                               if (cont_level >=
+                                   magic[magindex].cont_level) {
+                                       if (cont_level >
+                                           magic[magindex].cont_level) {
+                                               /*
+                                                * We're at the end of the
+                                                * level-"cont_level"
+                                                * continuations.
+                                                */
+                                               cont_level = 
+                                                 magic[magindex].cont_level;
+                                       }
+                                       if (mcheck(s, &magic[magindex])) {
+                                               /*
+                                                * This continuation matched.
+                                                * Print its message, with
+                                                * a blank before it if
+                                                * the previous item printed
+                                                * and this item isn't empty.
+                                                */
+                                               /* space if previous printed */
+                                               if (need_separator
+                                                  && (magic[magindex].nospflag == 0)
+                                                  && (magic[magindex].desc[0] != '\0')
+                                                  ) {
+                                                       (void) putchar(' ');
+                                                       need_separator = 0;
+                                               }
+                                               mprint(&magic[magindex],s);
+                                               if (magic[magindex].desc[0])
+                                                       need_separator = 1;
+
+                                               /*
+                                                * If we see any continuations
+                                                * at a higher level,
+                                                * process them.
+                                                */
+                                               cont_level++;
+                                       }
                                }
                        }
                        return 1;               /* all through */
                } else {
                        /* main entry didn't match, flush its continuation */
-                       while (magic[magindex+1].flag &&
+                       while (magic[magindex+1].cont_level != 0 &&
                                magindex < nmagic) {
                                ++magindex;
                        }
@@ -111,10 +176,14 @@ unsigned char *s;
                              (m->reln & MASK) ? p->b & m->mask : p->b);
                break;
        case SHORT:
+       case BESHORT:
+       case LESHORT:
                (void) printf(m->desc,
                              (m->reln & MASK) ? p->h & m->mask : p->h);
                break;
        case LONG:
+       case BELONG:
+       case LELONG:
                (void) printf(m->desc,
                              (m->reln & MASK) ? p->l & m->mask : p->l);
                break;
@@ -126,6 +195,8 @@ unsigned char *s;
                        *rt = '\n';
                break;
        case DATE:
+       case BEDATE:
+       case LEDATE:
                pp = ctime((time_t*) &p->l);
                if ((rt = strchr(pp, '\n')) != NULL)
                        *rt = '\0';
@@ -185,6 +256,22 @@ struct magic *m;
                                        break;
                }
                break;
+       case BESHORT:
+               v = (short)((p->hs[0]<<8)|(p->hs[1]));
+               break;
+       case BELONG:
+       case BEDATE:
+               v = (long)
+                   ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
+               break;
+       case LESHORT:
+               v = (short)((p->hs[1]<<8)|(p->hs[0]));
+               break;
+       case LELONG:
+       case LEDATE:
+               v = (long)
+                   ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
+               break;
        default:
                error("invalid type %d in mcheck().\n", m->type);
                return -1;/*NOTREACHED*/
@@ -197,7 +284,6 @@ struct magic *m;
        case 'x':
                return 1;
        case '!':
-       case '^':
                return v != l;
        case '=':
                return v == l;
@@ -207,6 +293,8 @@ struct magic *m;
                return v < l;
        case '&':
                return (v & l) == l;
+       case '^':
+               return (v & l) != l;
        case MASK | '=':
                return (v & mask) == l;
        case MASK | '>':