-/* $Id: roff.c,v 1.45 2008/12/06 16:50:18 kristaps Exp $ */
+/* $Id: roff.c,v 1.49 2008/12/07 16:41:04 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
static int textparse(struct rofftree *, char *);
static int roffdata(struct rofftree *, int, char *);
static int roffspecial(struct rofftree *, int,
- const char *, size_t, char **);
+ const char *, const int *,
+ const char **, size_t, char **);
static int roffsetname(struct rofftree *, char **);
#ifdef __linux__
static int
-roffspecial(struct rofftree *tree, int tok,
- const char *start, size_t sz, char **ordp)
+roffspecial(struct rofftree *tree, int tok, const char *start,
+ const int *argc, const char **argv,
+ size_t sz, char **ordp)
{
switch (tok) {
+ case (ROFF_At):
+ if (0 == sz)
+ break;
+ if (0 == strcmp(*ordp, "v6"))
+ break;
+ else if (0 == strcmp(*ordp, "v7"))
+ break;
+ else if (0 == strcmp(*ordp, "32v"))
+ break;
+ else if (0 == strcmp(*ordp, "V.1"))
+ break;
+ else if (0 == strcmp(*ordp, "V.4"))
+ break;
+ roff_err(tree, start, "invalid `At' arg");
+ return(0);
+
+ case (ROFF_Fn):
+ if (0 != sz)
+ break;
+ roff_err(tree, start, "`%s' expects at least "
+ "one arg", toknames[tok]);
+ return(0);
+
case (ROFF_Nm):
if (0 == sz) {
if (0 == tree->name[0]) {
return(0);
break;
+ case (ROFF_Rv):
+ /* FALLTHROUGH*/
+ case (ROFF_Sx):
+ /* FALLTHROUGH*/
case (ROFF_Ex):
- if (0 == sz) {
- roff_err(tree, start, "`Ex' expects an arg");
- return(0);
- } else if (1 != sz) {
- roff_err(tree, start, "`Ex' expects one arg");
- return(0);
- }
- break;
+ if (1 == sz)
+ break;
+ roff_err(tree, start, "`%s' expects one arg",
+ toknames[tok]);
+ return(0);
case (ROFF_Sm):
- if (0 == sz) {
- roff_err(tree, start, "`Sm' expects an arg");
- return(0);
- } else if (1 != sz) {
+ if (1 != sz) {
roff_err(tree, start, "`Sm' expects one arg");
return(0);
}
case (ROFF_Ud):
/* FALLTHROUGH */
+ case (ROFF_Ux):
+ /* FALLTHROUGH */
case (ROFF_Bt):
if (0 != sz) {
roff_err(tree, start, "`%s' expects no args",
break;
}
- return((*tree->cb.roffspecial)
- (tree->arg, tok, tree->cur, ordp));
+ return((*tree->cb.roffspecial)(tree->arg, tok,
+ tree->cur, argc, argv, ordp));
}
argv++;
- if (0 == strcmp(*argv, "$Mdocdate: December 6 2008 $")) {
+ if (0 == strcmp(*argv, "$Mdocdate: December 7 2008 $")) {
t = time(NULL);
if (NULL == localtime_r(&t, &tree->tm))
err(1, "localtime_r");
}
-/* ARGSUSED */
-static int
-roff_Sm(ROFFCALL_ARGS)
-{
- char *ordp[1], *p;
-
- p = *argv++;
- *ordp = *argv;
-
- return(roffspecial(tree, tok, p, *ordp ? 1 : 0, ordp));
-}
-
-
/* ARGSUSED */
static int
roff_Ns(ROFFCALL_ARGS)
first = (*argv++ == tree->cur);
morep[0] = NULL;
- if ( ! roffspecial(tree, tok, *argv, 0, morep))
+ if ( ! roffspecial(tree, tok, *argv, NULL, NULL, 0, morep))
return(0);
while (*argv) {
if ( ! roffparseopts(tree, tok, &argv, argcp, argvp))
return(0);
- if (NULL == *argv)
- return(roffspecial(tree, tok, p, 0, ordp));
+ if (NULL == *argv) {
+ ordp[0] = NULL;
+ return(roffspecial(tree, tok, p, argcp,
+ (const char **)argvp, 0, ordp));
+ }
i = 0;
while (*argv && i < ROFF_MAXLINEARG) {
- c = rofffindcallable(*argv);
+ c = ROFF_PARSED & tokens[tok].flags ?
+ rofffindcallable(*argv) : ROFF_MAX;
if (ROFF_MAX == c && ! roffispunct(*argv)) {
ordp[i++] = *argv++;
if (ROFF_MAX == c)
break;
- if ( ! roffspecial(tree, tok, p, (size_t)i, ordp))
+ if ( ! roffspecial(tree, tok, p, argcp,
+ (const char **)argvp,
+ (size_t)i, ordp))
return(0);
- return(roffcall(tree, c, ordp));
+ return(roffcall(tree, c, argv));
}
assert(i != ROFF_MAXLINEARG);
ordp[i] = NULL;
- if ( ! roffspecial(tree, tok, p, (size_t)i, ordp))
+ if ( ! roffspecial(tree, tok, p, argcp,
+ (const char**)argvp,
+ (size_t)i, ordp))
return(0);
/* FIXME: error if there's stuff after the punctuation. */
* terminating punctuation. If we encounter it and all
* subsequent tokens are punctuation, then stop processing (the
* line-dominant macro will print these tokens after closure).
+ * If the punctuation is followed by non-punctuation, then close
+ * and re-open our scope, then continue.
*/
i = 0;
break;
if (argv[j]) {
+ if (ROFF_LSCOPE & tokens[tok].flags) {
+ if ( ! roffdata(tree, 0, *argv++))
+ return(0);
+ continue;
+ }
+ if ( ! (*tree->cb.roffout)(tree->arg, tok))
+ return(0);
if ( ! roffdata(tree, 0, *argv++))
return(0);
+ if ( ! (*tree->cb.roffin)(tree->arg, tok,
+ argcp, argvp))
+ return(0);
+
+ i = 0;
continue;
}