#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 *));
}
/*
- * 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;
}
(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;
*rt = '\n';
break;
case DATE:
+ case BEDATE:
+ case LEDATE:
pp = ctime((time_t*) &p->l);
if ((rt = strchr(pp, '\n')) != NULL)
*rt = '\0';
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*/
case 'x':
return 1;
case '!':
- case '^':
return v != l;
case '=':
return v == l;
return v < l;
case '&':
return (v & l) == l;
+ case '^':
+ return (v & l) != l;
case MASK | '=':
return (v & mask) == l;
case MASK | '>':