=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/mandoc/roff.c,v retrieving revision 1.70 retrieving revision 1.71 diff -c -r1.70 -r1.71 *** src/usr.bin/mandoc/roff.c 2014/03/07 18:37:32 1.70 --- src/usr.bin/mandoc/roff.c 2014/03/08 04:43:39 1.71 *************** *** 1,4 **** ! /* $Id: roff.c,v 1.70 2014/03/07 18:37:32 schwarze Exp $ */ /* * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons * Copyright (c) 2010-2014 Ingo Schwarze --- 1,4 ---- ! /* $Id: roff.c,v 1.71 2014/03/08 04:43:39 schwarze Exp $ */ /* * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons * Copyright (c) 2010-2014 Ingo Schwarze *************** *** 72,82 **** ROFF_MAX }; - enum roffrule { - ROFFRULE_DENY, - ROFFRULE_ALLOW - }; - /* * An incredibly-simple string buffer. */ --- 72,77 ---- *************** *** 108,114 **** struct mparse *parse; /* parse point */ int quick; /* skip standard macro deletion */ struct roffnode *last; /* leaf of stack */ ! enum roffrule rstack[RSTACK_MAX]; /* stack of !`ie' rules */ char control; /* control character */ int rstackpos; /* position in rstack */ struct roffreg *regtab; /* number registers */ --- 103,109 ---- struct mparse *parse; /* parse point */ int quick; /* skip standard macro deletion */ struct roffnode *last; /* leaf of stack */ ! int rstack[RSTACK_MAX]; /* stack of !`ie' rules */ char control; /* control character */ int rstackpos; /* position in rstack */ struct roffreg *regtab; /* number registers */ *************** *** 132,138 **** char *name; /* node name, e.g. macro name */ char *end; /* end-rules: custom token */ int endspan; /* end-rules: next-line or infty */ ! enum roffrule rule; /* current evaluation rule */ }; #define ROFF_ARGS struct roff *r, /* parse ctx */ \ --- 127,133 ---- char *name; /* node name, e.g. macro name */ char *end; /* end-rules: custom token */ int endspan; /* end-rules: next-line or infty */ ! int rule; /* current evaluation rule */ }; #define ROFF_ARGS struct roff *r, /* parse ctx */ \ *************** *** 180,186 **** static enum rofferr roff_cond_text(ROFF_ARGS); static enum rofferr roff_cond_sub(ROFF_ARGS); static enum rofferr roff_ds(ROFF_ARGS); ! static enum roffrule roff_evalcond(const char *, int *); static void roff_free1(struct roff *); static void roff_freereg(struct roffreg *); static void roff_freestr(struct roffkv *); --- 175,182 ---- static enum rofferr roff_cond_text(ROFF_ARGS); static enum rofferr roff_cond_sub(ROFF_ARGS); static enum rofferr roff_ds(ROFF_ARGS); ! static int roff_evalcond(const char *, int *); ! static int roff_evalstrcond(const char *, int *); static void roff_free1(struct roff *); static void roff_freereg(struct roffreg *); static void roff_freestr(struct roffkv *); *************** *** 397,403 **** p->parent = r->last; p->line = line; p->col = col; ! p->rule = p->parent ? p->parent->rule : ROFFRULE_DENY; r->last = p; } --- 393,399 ---- p->parent = r->last; p->line = line; p->col = col; ! p->rule = p->parent ? p->parent->rule : 0; r->last = p; } *************** *** 1046,1053 **** roff_cond_sub(ROFF_ARGS) { enum rofft t; - enum roffrule rr; char *ep; rr = r->last->rule; roffnode_cleanscope(r); --- 1042,1049 ---- roff_cond_sub(ROFF_ARGS) { enum rofft t; char *ep; + int rr; rr = r->last->rule; roffnode_cleanscope(r); *************** *** 1059,1066 **** */ if ((ROFF_MAX != t) && ! (ROFFRULE_ALLOW == rr || ! ROFFMAC_STRUCT & roffs[t].flags)) { assert(roffs[t].proc); return((*roffs[t].proc)(r, t, bufp, szp, ln, ppos, pos, offs)); --- 1055,1061 ---- */ if ((ROFF_MAX != t) && ! (rr || ROFFMAC_STRUCT & roffs[t].flags)) { assert(roffs[t].proc); return((*roffs[t].proc)(r, t, bufp, szp, ln, ppos, pos, offs)); *************** *** 1073,1079 **** ep = *bufp + pos; if ('\\' == ep[0] && '}' == ep[1]) ! rr = ROFFRULE_DENY; /* Always check for the closing delimiter `\}'. */ --- 1068,1074 ---- ep = *bufp + pos; if ('\\' == ep[0] && '}' == ep[1]) ! rr = 0; /* Always check for the closing delimiter `\}'. */ *************** *** 1084,1090 **** } ++ep; } ! return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); } /* ARGSUSED */ --- 1079,1085 ---- } ++ep; } ! return(rr ? ROFF_CONT : ROFF_IGN); } /* ARGSUSED */ *************** *** 1092,1098 **** roff_cond_text(ROFF_ARGS) { char *ep; ! enum roffrule rr; rr = r->last->rule; roffnode_cleanscope(r); --- 1087,1093 ---- roff_cond_text(ROFF_ARGS) { char *ep; ! int rr; rr = r->last->rule; roffnode_cleanscope(r); *************** *** 1105,1111 **** } ++ep; } ! return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT); } static int --- 1100,1106 ---- } ++ep; } ! return(rr ? ROFF_CONT : ROFF_IGN); } static int *************** *** 1158,1221 **** return(*res); } ! static enum roffrule roff_evalcond(const char *v, int *pos) { ! int not, lh, rh; char op; switch (v[*pos]) { case ('n'): (*pos)++; ! return(ROFFRULE_ALLOW); case ('e'): /* FALLTHROUGH */ ! case ('o'): /* FALLTHROUGH */ case ('t'): (*pos)++; ! return(ROFFRULE_DENY); ! case ('!'): ! (*pos)++; ! not = 1; ! break; default: - not = 0; break; } if (!roff_getnum(v, pos, &lh)) ! return ROFFRULE_DENY; ! if (!roff_getop(v, pos, &op)) { ! if (lh < 0) ! lh = 0; ! goto out; ! } if (!roff_getnum(v, pos, &rh)) ! return ROFFRULE_DENY; switch (op) { case 'g': ! lh = lh >= rh; ! break; case 'l': ! lh = lh <= rh; ! break; case '=': ! lh = lh == rh; ! break; case '>': ! lh = lh > rh; ! break; case '<': ! lh = lh < rh; ! break; default: ! return ROFFRULE_DENY; } - out: - if (not) - lh = !lh; - return lh ? ROFFRULE_ALLOW : ROFFRULE_DENY; } /* ARGSUSED */ --- 1153,1255 ---- return(*res); } ! /* ! * Evaluate a string comparison condition. ! * The first character is the delimiter. ! * Succeed if the string up to its second occurrence ! * matches the string up to its third occurence. ! * Advance the cursor after the third occurrence ! * or lacking that, to the end of the line. ! */ ! static int ! roff_evalstrcond(const char *v, int *pos) ! { ! const char *s1, *s2, *s3; ! int match; ! ! match = 0; ! s1 = v + *pos; /* initial delimiter */ ! s2 = s1 + 1; /* for scanning the first string */ ! s3 = strchr(s2, *s1); /* for scanning the second string */ ! ! if (NULL == s3) /* found no middle delimiter */ ! goto out; ! ! while ('\0' != *++s3) { ! if (*s2 != *s3) { /* mismatch */ ! s3 = strchr(s3, *s1); ! break; ! } ! if (*s3 == *s1) { /* found the final delimiter */ ! match = 1; ! break; ! } ! s2++; ! } ! ! out: ! if (NULL == s3) ! s3 = strchr(s2, '\0'); ! else ! s3++; ! *pos = s3 - v; ! return(match); ! } ! ! static int roff_evalcond(const char *v, int *pos) { ! int wanttrue, lh, rh; char op; + if ('!' == v[*pos]) { + wanttrue = 0; + (*pos)++; + } else + wanttrue = 1; + switch (v[*pos]) { case ('n'): + /* FALLTHROUGH */ + case ('o'): (*pos)++; ! return(wanttrue); ! case ('c'): ! /* FALLTHROUGH */ ! case ('d'): ! /* FALLTHROUGH */ case ('e'): /* FALLTHROUGH */ ! case ('r'): /* FALLTHROUGH */ case ('t'): (*pos)++; ! return(!wanttrue); default: break; } if (!roff_getnum(v, pos, &lh)) ! return(roff_evalstrcond(v, pos) == wanttrue); ! if (!roff_getop(v, pos, &op)) ! return((lh > 0) == wanttrue); if (!roff_getnum(v, pos, &rh)) ! return(0); ! switch (op) { case 'g': ! return((lh >= rh) == wanttrue); case 'l': ! return((lh <= rh) == wanttrue); case '=': ! return((lh == rh) == wanttrue); case '>': ! return((lh > rh) == wanttrue); case '<': ! return((lh < rh) == wanttrue); default: ! return(0); } } /* ARGSUSED */ *************** *** 1242,1249 **** */ r->last->rule = ROFF_el == tok ? ! (r->rstackpos < 0 ? ! ROFFRULE_DENY : r->rstack[r->rstackpos--]) : roff_evalcond(*bufp, &pos); /* --- 1276,1282 ---- */ r->last->rule = ROFF_el == tok ? ! (r->rstackpos < 0 ? 0 : r->rstack[r->rstackpos--]) : roff_evalcond(*bufp, &pos); /* *************** *** 1257,1271 **** r->parse, ln, ppos, NULL); return(ROFF_ERR); } ! r->rstack[++r->rstackpos] = ! ROFFRULE_DENY == r->last->rule ? ! ROFFRULE_ALLOW : ROFFRULE_DENY; } /* If the parent has false as its rule, then so do we. */ ! if (r->last->parent && ROFFRULE_DENY == r->last->parent->rule) ! r->last->rule = ROFFRULE_DENY; /* * Determine scope. --- 1290,1302 ---- r->parse, ln, ppos, NULL); return(ROFF_ERR); } ! r->rstack[++r->rstackpos] = !r->last->rule; } /* If the parent has false as its rule, then so do we. */ ! if (r->last->parent && !r->last->parent->rule) ! r->last->rule = 0; /* * Determine scope.