-/* $Id: roff.c,v 1.238 2014/11/01 06:03:13 schwarze Exp $ */
+/* $Id: roff.c,v 1.244 2014/12/18 17:43:41 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
enum rofft t;
enum rofferr e;
int pos; /* parse point */
+ int spos; /* saved parse point for messages */
int ppos; /* original offset in buf->buf */
int ctl; /* macro line (boolean) */
return((*roffs[t].sub)(r, t, buf, ln, ppos, pos, offs));
}
+ /* No scope is open. This is a new request or macro. */
+
+ spos = pos;
+ t = roff_parse(r, buf->buf, &pos, ln, ppos);
+
+ /* Tables ignore most macros. */
+
+ if (r->tbl != NULL && (t == ROFF_MAX || t == ROFF_TS)) {
+ mandoc_msg(MANDOCERR_TBLMACRO, r->parse,
+ ln, pos, buf->buf + spos);
+ return(ROFF_IGN);
+ }
+
/*
- * Lastly, as we've no scope open, try to look up and execute
- * the new macro. If no macro is found, simply return and let
- * the compilers handle it.
+ * This is neither a roff request nor a user-defined macro.
+ * Let the standard macro set parsers handle it.
*/
- if ((t = roff_parse(r, buf->buf, &pos, ln, ppos)) == ROFF_MAX)
+ if (t == ROFF_MAX)
return(ROFF_CONT);
+ /* Execute a roff request or a user defined macro. */
+
assert(roffs[t].proc);
return((*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs));
}
out:
if (NULL == s3)
s3 = strchr(s2, '\0');
- else
+ else if (*s3 != '\0')
s3++;
*pos = s3 - v;
return(match);
static int
roff_evalcond(struct roff *r, int ln, const char *v, int *pos)
{
- int wanttrue, number;
+ int number, savepos, wanttrue;
if ('!' == v[*pos]) {
wanttrue = 0;
wanttrue = 1;
switch (v[*pos]) {
+ case '\0':
+ return(0);
case 'n':
/* FALLTHROUGH */
case 'o':
case 'r':
/* FALLTHROUGH */
case 't':
+ /* FALLTHROUGH */
+ case 'v':
(*pos)++;
return(!wanttrue);
default:
break;
}
+ savepos = *pos;
if (roff_evalnum(r, ln, v, pos, &number, 0))
return((number > 0) == wanttrue);
- else
+ else if (*pos == savepos)
return(roff_evalstrcond(v, pos) == wanttrue);
+ else
+ return (0);
}
static enum rofferr
*res *= operand2;
break;
case '/':
- if (0 == operand2) {
+ if (operand2 == 0) {
mandoc_msg(MANDOCERR_DIVZERO,
r->parse, ln, *pos, v);
*res = 0;
*res /= operand2;
break;
case '%':
+ if (operand2 == 0) {
+ mandoc_msg(MANDOCERR_DIVZERO,
+ r->parse, ln, *pos, v);
+ *res = 0;
+ break;
+ }
*res %= operand2;
break;
case '<':