version 1.51, 2009/03/14 05:21:58 |
version 1.55, 2009/03/21 21:09:00 |
|
|
/* $Id$ */ |
/* $Id$ */ |
/* |
/* |
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se> |
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the |
* purpose with or without fee is hereby granted, provided that the |
|
|
#define ARGV_MULTI (1 << 2) |
#define ARGV_MULTI (1 << 2) |
#define ARGV_OPT_SINGLE (1 << 3) |
#define ARGV_OPT_SINGLE (1 << 3) |
|
|
|
#define MULTI_STEP 5 |
|
|
enum mwarn { |
enum mwarn { |
WQUOTPARM, |
WQUOTPARM, |
WARGVPARM, |
WARGVPARM, |
Line 218 static int mdoc_argflags[MDOC_MAX] = { |
|
Line 220 static int mdoc_argflags[MDOC_MAX] = { |
|
0, /* Bro */ |
0, /* Bro */ |
ARGS_DELIM, /* Brc */ |
ARGS_DELIM, /* Brc */ |
ARGS_QUOTED, /* %C */ |
ARGS_QUOTED, /* %C */ |
|
0, /* Es */ |
|
0, /* En */ |
|
0, /* Dx */ |
|
ARGS_QUOTED, /* %Q */ |
}; |
}; |
|
|
|
|
Line 238 mdoc_argv(struct mdoc *mdoc, int line, int tok, |
|
Line 244 mdoc_argv(struct mdoc *mdoc, int line, int tok, |
|
if (0 == buf[*pos]) |
if (0 == buf[*pos]) |
return(ARGV_EOLN); |
return(ARGV_EOLN); |
|
|
assert( ! isspace((u_char)buf[*pos])); |
assert(' ' != buf[*pos]); |
|
|
if ('-' != buf[*pos]) |
if ('-' != buf[*pos] || ARGS_ARGVLIKE & mdoc_argflags[tok]) |
return(ARGV_WORD); |
return(ARGV_WORD); |
|
|
|
/* Parse through to the first unescaped space. */ |
|
|
i = *pos; |
i = *pos; |
p = &buf[++(*pos)]; |
p = &buf[++(*pos)]; |
|
|
Line 250 mdoc_argv(struct mdoc *mdoc, int line, int tok, |
|
Line 258 mdoc_argv(struct mdoc *mdoc, int line, int tok, |
|
|
|
/* LINTED */ |
/* LINTED */ |
while (buf[*pos]) { |
while (buf[*pos]) { |
if (isspace((u_char)buf[*pos])) |
if (' ' == buf[*pos]) |
if ('\\' != buf[*pos - 1]) |
if ('\\' != buf[*pos - 1]) |
break; |
break; |
(*pos)++; |
(*pos)++; |
} |
} |
|
|
/* |
/* XXX - save zeroed byte, if not an argument. */ |
* XXX: save the nullified byte as we'll restore it if this |
|
* doesn't end up being a command after all. This is a little |
|
* bit hacky. I don't like it, but it works for now. |
|
*/ |
|
|
|
sv = 0; |
sv = 0; |
if (buf[*pos]) { |
if (buf[*pos]) { |
Line 272 mdoc_argv(struct mdoc *mdoc, int line, int tok, |
|
Line 276 mdoc_argv(struct mdoc *mdoc, int line, int tok, |
|
tmp.line = line; |
tmp.line = line; |
tmp.pos = *pos; |
tmp.pos = *pos; |
|
|
/* |
/* See if our token accepts the argument. */ |
* We now parse out the per-macro arguments. XXX - this can be |
|
* made much cleaner using per-argument tables. See argv_a2arg |
|
* for details. |
|
*/ |
|
|
|
if (MDOC_ARG_MAX == (tmp.arg = argv_a2arg(tok, p))) { |
if (MDOC_ARG_MAX == (tmp.arg = argv_a2arg(tok, p))) { |
/* XXX - restore saved byte. */ |
/* XXX - restore saved zeroed byte. */ |
if (sv) |
if (sv) |
buf[*pos - 1] = sv; |
buf[*pos - 1] = sv; |
if ( ! pwarn(mdoc, line, i, WARGVPARM)) |
if ( ! pwarn(mdoc, line, i, WARGVPARM)) |
Line 287 mdoc_argv(struct mdoc *mdoc, int line, int tok, |
|
Line 287 mdoc_argv(struct mdoc *mdoc, int line, int tok, |
|
return(ARGV_WORD); |
return(ARGV_WORD); |
} |
} |
|
|
while (buf[*pos] && isspace((u_char)buf[*pos])) |
while (buf[*pos] && ' ' == buf[*pos]) |
(*pos)++; |
(*pos)++; |
|
|
/* FIXME: whitespace if no value. */ |
|
|
|
if ( ! argv(mdoc, line, &tmp, pos, buf)) |
if ( ! argv(mdoc, line, &tmp, pos, buf)) |
return(ARGV_ERROR); |
return(ARGV_ERROR); |
|
|
Line 332 mdoc_argv_free(struct mdoc_arg *p) |
|
Line 330 mdoc_argv_free(struct mdoc_arg *p) |
|
if (0 == p->argv[i].sz) |
if (0 == p->argv[i].sz) |
continue; |
continue; |
/* LINTED */ |
/* LINTED */ |
for (j = 0; j < (int)p->argv[i].sz; j++) |
for (j = 0; j < (int)p->argv[i].sz; j++) |
free(p->argv[i].value[j]); |
free(p->argv[i].value[j]); |
|
|
free(p->argv[i].value); |
free(p->argv[i].value); |
Line 448 mdoc_args(struct mdoc *mdoc, int line, |
|
Line 446 mdoc_args(struct mdoc *mdoc, int line, |
|
break; |
break; |
} |
} |
|
|
/* Continue parsing the arguments themselves... */ |
|
|
|
return(args(mdoc, line, pos, buf, fl, v)); |
return(args(mdoc, line, pos, buf, fl, v)); |
} |
} |
|
|
Line 486 args(struct mdoc *mdoc, int line, |
|
Line 482 args(struct mdoc *mdoc, int line, |
|
break; |
break; |
i++; |
i++; |
/* There must be at least one space... */ |
/* There must be at least one space... */ |
if (0 == buf[i] || ! isspace((u_char)buf[i])) |
if (0 == buf[i] || ' ' != buf[i]) |
break; |
break; |
i++; |
i++; |
while (buf[i] && isspace((u_char)buf[i])) |
while (buf[i] && ' ' == buf[i]) |
i++; |
i++; |
} |
} |
if (0 == buf[i]) { |
if (0 == buf[i]) { |
Line 505 args(struct mdoc *mdoc, int line, |
|
Line 501 args(struct mdoc *mdoc, int line, |
|
|
|
/* |
/* |
* Thar be dragons here! If we're tab-separated, search |
* Thar be dragons here! If we're tab-separated, search |
* ahead for either a tab or the `Ta' macro. If a tab |
* ahead for either a tab or the `Ta' macro. |
* is detected, it mustn't be escaped; if a `Ta' is |
* If a `Ta' is detected, it must be space-buffered before and |
* detected, it must be space-buffered before and after. |
* after. If either of these hold true, then prune out the |
* If either of these hold true, then prune out the |
|
* extra spaces and call it an argument. |
* extra spaces and call it an argument. |
*/ |
*/ |
|
|
if (ARGS_TABSEP & fl) { |
if (ARGS_TABSEP & fl) { |
/* Scan ahead to unescaped tab. */ |
/* Scan ahead to unescaped tab. */ |
|
|
for (p = *v; ; p++) { |
p = strchr(*v, '\t'); |
if (NULL == (p = strchr(p, '\t'))) |
|
break; |
|
if (p == *v) |
|
break; |
|
if ('\\' != *(p - 1)) |
|
break; |
|
} |
|
|
|
/* Scan ahead to unescaped `Ta'. */ |
/* Scan ahead to unescaped `Ta'. */ |
|
|
Line 597 args(struct mdoc *mdoc, int line, |
|
Line 585 args(struct mdoc *mdoc, int line, |
|
|
|
if ( ! (ARGS_TABSEP & fl)) |
if ( ! (ARGS_TABSEP & fl)) |
while (buf[*pos]) { |
while (buf[*pos]) { |
if (isspace((u_char)buf[*pos])) |
if (' ' == buf[*pos]) |
if ('\\' != buf[*pos - 1]) |
if ('\\' != buf[*pos - 1]) |
break; |
break; |
(*pos)++; |
(*pos)++; |
Line 612 args(struct mdoc *mdoc, int line, |
|
Line 600 args(struct mdoc *mdoc, int line, |
|
return(ARGS_WORD); |
return(ARGS_WORD); |
|
|
if ( ! (ARGS_TABSEP & fl)) |
if ( ! (ARGS_TABSEP & fl)) |
while (buf[*pos] && isspace((u_char)buf[*pos])) |
while (buf[*pos] && ' ' == buf[*pos]) |
(*pos)++; |
(*pos)++; |
|
|
if (buf[*pos]) |
if (buf[*pos]) |
Line 644 args(struct mdoc *mdoc, int line, |
|
Line 632 args(struct mdoc *mdoc, int line, |
|
if (0 == buf[*pos]) |
if (0 == buf[*pos]) |
return(ARGS_QWORD); |
return(ARGS_QWORD); |
|
|
while (buf[*pos] && isspace((u_char)buf[*pos])) |
while (buf[*pos] && ' ' == buf[*pos]) |
(*pos)++; |
(*pos)++; |
|
|
if (buf[*pos]) |
if (buf[*pos]) |
Line 773 argv_multi(struct mdoc *mdoc, int line, |
|
Line 761 argv_multi(struct mdoc *mdoc, int line, |
|
else if (ARGS_EOLN == c) |
else if (ARGS_EOLN == c) |
break; |
break; |
|
|
if (0 == v->sz % 5) |
if (0 == v->sz % MULTI_STEP) |
v->value = xrealloc(v->value, |
v->value = xrealloc(v->value, |
(v->sz + 5) * sizeof(char *)); |
(v->sz + MULTI_STEP) * sizeof(char *)); |
|
|
v->value[(int)v->sz] = xstrdup(p); |
v->value[(int)v->sz] = xstrdup(p); |
} |
} |