Annotation of mandoc/argv.c, Revision 1.2
1.2 ! kristaps 1: /* $Id: argv.c,v 1.1 2008/12/23 05:30:49 kristaps Exp $ */
1.1 kristaps 2: /*
3: * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the
7: * above copyright notice and this permission notice appear in all
8: * copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11: * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12: * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13: * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16: * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17: * PERFORMANCE OF THIS SOFTWARE.
18: */
19: #include <assert.h>
20: #include <ctype.h>
21: #include <err.h>
22: #include <stdlib.h>
23: #include <stdio.h>
24: #include <string.h>
25:
26: #include "private.h"
27:
28:
1.2 ! kristaps 29: static int lookup(int, const char *);
! 30: static int parse(struct mdoc *, int,
! 31: struct mdoc_arg *, int *, char *);
! 32: static int postparse(struct mdoc *, int,
! 33: const struct mdoc_arg *, int);
1.1 kristaps 34:
35:
1.2 ! kristaps 36: int
! 37: mdoc_args(struct mdoc *mdoc, int tok, int *pos, char *buf, int fl, char **v)
1.1 kristaps 38: {
1.2 ! kristaps 39: int i;
1.1 kristaps 40:
41: if (0 == buf[*pos])
1.2 ! kristaps 42: return(ARGS_EOLN);
! 43:
! 44: if ('\"' == buf[*pos] && ! (fl & ARGS_QUOTED))
! 45: if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_QUOTED))
! 46: return(ARGS_ERROR);
! 47:
! 48: if ('-' == buf[*pos])
! 49: if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_ARGLIKE))
! 50: return(ARGS_ERROR);
! 51:
! 52: if ((fl & ARGS_DELIM) && mdoc_iscdelim(buf[*pos])) {
! 53: for (i = *pos; buf[i]; ) {
! 54: if ( ! mdoc_iscdelim(buf[i]))
! 55: break;
! 56: i++;
! 57: if (0 == buf[i] || ! isspace(buf[i]))
! 58: break;
! 59: i++;
! 60: while (buf[i] && isspace(buf[i]))
! 61: i++;
! 62: }
! 63: if (0 == buf[i]) {
! 64: *v = &buf[*pos];
! 65: return(ARGS_PUNCT);
! 66: }
! 67: }
! 68:
! 69: /*
! 70: * Parse routine for non-quoted string.
! 71: */
1.1 kristaps 72:
73: if ('\"' != buf[*pos]) {
74: *v = &buf[*pos];
75:
76: while (buf[*pos] && ! isspace(buf[*pos]))
77: (*pos)++;
78:
79: if (0 == buf[*pos])
1.2 ! kristaps 80: return(ARGS_WORD);
1.1 kristaps 81:
82: buf[(*pos)++] = 0;
83: if (0 == buf[*pos])
1.2 ! kristaps 84: return(ARGS_WORD);
1.1 kristaps 85:
86: while (buf[*pos] && isspace(buf[*pos]))
87: (*pos)++;
88:
89: if (buf[*pos])
1.2 ! kristaps 90: return(ARGS_WORD);
1.1 kristaps 91:
92: if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_WS_EOLN))
1.2 ! kristaps 93: return(ARGS_ERROR);
1.1 kristaps 94:
1.2 ! kristaps 95: return(ARGS_WORD);
! 96: }
! 97:
! 98: /*
! 99: * If we're a quoted string (and quoted strings are allowed),
! 100: * then parse ahead to the next quote. If none's found, it's an
! 101: * error. After, parse to the next word. We're not allowed to
! 102: * also be DELIM requests (for now).
! 103: */
! 104: assert( ! (fl & ARGS_DELIM));
1.1 kristaps 105:
106: *v = &buf[++(*pos)];
107:
108: while (buf[*pos] && '\"' != buf[*pos])
109: (*pos)++;
110:
111: if (0 == buf[*pos]) {
112: (void)mdoc_err(mdoc, tok, *pos, ERR_SYNTAX_UNQUOTE);
1.2 ! kristaps 113: return(ARGS_ERROR);
1.1 kristaps 114: }
115:
116: buf[(*pos)++] = 0;
117: if (0 == buf[*pos])
1.2 ! kristaps 118: return(ARGS_WORD);
1.1 kristaps 119:
120: while (buf[*pos] && isspace(buf[*pos]))
121: (*pos)++;
122:
123: if (buf[*pos])
1.2 ! kristaps 124: return(ARGS_WORD);
1.1 kristaps 125:
126: if ( ! mdoc_warn(mdoc, tok, *pos, WARN_SYNTAX_WS_EOLN))
1.2 ! kristaps 127: return(ARGS_ERROR);
! 128:
! 129: return(ARGS_WORD);
1.1 kristaps 130: }
131:
132:
1.2 ! kristaps 133: static int
! 134: lookup(int tok, const char *argv)
1.1 kristaps 135: {
136:
137: switch (tok) {
1.2 ! kristaps 138: case (MDOC_Bd):
1.1 kristaps 139: if (xstrcmp(argv, "ragged"))
140: return(MDOC_Ragged);
141: else if (xstrcmp(argv, "unfilled"))
142: return(MDOC_Unfilled);
143: else if (xstrcmp(argv, "literal"))
144: return(MDOC_Literal);
145: else if (xstrcmp(argv, "file"))
146: return(MDOC_File);
147: else if (xstrcmp(argv, "offset"))
148: return(MDOC_Offset);
1.2 ! kristaps 149: break;
! 150:
! 151: case (MDOC_Bl):
! 152: if (xstrcmp(argv, "bullet"))
1.1 kristaps 153: return(MDOC_Bullet);
154: else if (xstrcmp(argv, "dash"))
155: return(MDOC_Dash);
156: else if (xstrcmp(argv, "hyphen"))
157: return(MDOC_Hyphen);
158: else if (xstrcmp(argv, "item"))
159: return(MDOC_Item);
160: else if (xstrcmp(argv, "enum"))
161: return(MDOC_Enum);
162: else if (xstrcmp(argv, "tag"))
163: return(MDOC_Tag);
164: else if (xstrcmp(argv, "diag"))
165: return(MDOC_Diag);
166: else if (xstrcmp(argv, "hang"))
167: return(MDOC_Hang);
168: else if (xstrcmp(argv, "ohang"))
169: return(MDOC_Ohang);
170: else if (xstrcmp(argv, "inset"))
171: return(MDOC_Inset);
172: else if (xstrcmp(argv, "column"))
173: return(MDOC_Column);
174: else if (xstrcmp(argv, "width"))
175: return(MDOC_Width);
1.2 ! kristaps 176: else if (xstrcmp(argv, "offset"))
! 177: return(MDOC_Offset);
1.1 kristaps 178: else if (xstrcmp(argv, "compact"))
179: return(MDOC_Compact);
1.2 ! kristaps 180: break;
1.1 kristaps 181:
182: default:
183: abort();
184: /* NOTREACHED */
185: }
186:
187: return(MDOC_ARG_MAX);
188: }
189:
190:
1.2 ! kristaps 191: static int
! 192: postparse(struct mdoc *mdoc, int tok, const struct mdoc_arg *v, int pos)
! 193: {
! 194:
! 195: switch (v->arg) {
! 196: case (MDOC_Offset):
! 197: assert(v->value);
! 198: assert(v->value[0]);
! 199: if (xstrcmp(v->value[0], "left"))
! 200: break;
! 201: if (xstrcmp(v->value[0], "right"))
! 202: break;
! 203: if (xstrcmp(v->value[0], "center"))
! 204: break;
! 205: if (xstrcmp(v->value[0], "indent"))
! 206: break;
! 207: if (xstrcmp(v->value[0], "indent-two"))
! 208: break;
! 209: return(mdoc_err(mdoc, tok, pos, ERR_SYNTAX_ARGBAD));
! 210: default:
! 211: break;
! 212: }
! 213:
! 214: return(1);
! 215: }
! 216:
! 217:
! 218: static int
! 219: parse(struct mdoc *mdoc, int tok,
1.1 kristaps 220: struct mdoc_arg *v, int *pos, char *buf)
221: {
222: char *p;
223: int c, ppos, i;
224:
225: ppos = *pos;
226:
1.2 ! kristaps 227: switch (v->arg) {
1.1 kristaps 228: case(MDOC_Compact):
229: /* FALLTHROUGH */
230: case(MDOC_Ragged):
231: /* FALLTHROUGH */
232: case(MDOC_Unfilled):
233: /* FALLTHROUGH */
234: case(MDOC_Literal):
235: /* FALLTHROUGH */
236: case(MDOC_File):
237: /* FALLTHROUGH */
238: case(MDOC_Bullet):
239: /* FALLTHROUGH */
240: case(MDOC_Dash):
241: /* FALLTHROUGH */
242: case(MDOC_Hyphen):
243: /* FALLTHROUGH */
244: case(MDOC_Item):
245: /* FALLTHROUGH */
246: case(MDOC_Enum):
247: /* FALLTHROUGH */
248: case(MDOC_Tag):
249: /* FALLTHROUGH */
250: case(MDOC_Diag):
251: /* FALLTHROUGH */
252: case(MDOC_Hang):
253: /* FALLTHROUGH */
254: case(MDOC_Ohang):
255: /* FALLTHROUGH */
256: case(MDOC_Inset):
257: v->sz = 0;
258: v->value = NULL;
259: break;
260:
261: case(MDOC_Width):
262: /* FALLTHROUGH */
263: case(MDOC_Offset):
264: /*
265: * This has a single value for an argument.
266: */
1.2 ! kristaps 267: c = mdoc_args(mdoc, tok, pos, buf, ARGS_QUOTED, &p);
! 268: if (ARGS_ERROR == c)
1.1 kristaps 269: return(0);
1.2 ! kristaps 270: else if (ARGS_EOLN == c)
1.1 kristaps 271: return(mdoc_err(mdoc, tok, ppos, ERR_SYNTAX_ARGVAL));
272:
273: v->sz = 1;
274: v->value = xcalloc(1, sizeof(char *));
275: v->value[0] = p;
276: break;
277:
278: case(MDOC_Column):
279: /*
280: * This has several value for a single argument. We
281: * pre-allocate a pointer array and don't let it exceed
282: * this size.
283: */
284: v->sz = 0;
285: v->value = xcalloc(MDOC_LINEARG_MAX, sizeof(char *));
286: for (i = 0; i < MDOC_LINEARG_MAX; i++) {
1.2 ! kristaps 287: c = mdoc_args(mdoc, tok, pos, buf, ARGS_QUOTED, &p);
! 288: if (ARGS_ERROR == c) {
1.1 kristaps 289: free(v->value);
290: return(0);
1.2 ! kristaps 291: } else if (ARGS_EOLN == c)
1.1 kristaps 292: break;
293: v->value[i] = p;
294: }
295: if (0 == i) {
296: free(v->value);
297: return(mdoc_err(mdoc, tok, ppos, ERR_SYNTAX_ARGVAL));
298: } else if (MDOC_LINEARG_MAX == i)
299: return(mdoc_err(mdoc, tok, ppos, ERR_SYNTAX_ARGMANY));
300:
301: v->sz = i;
302: break;
303: default:
304: abort();
305: /* NOTREACHED */
306: }
307:
308: return(1);
309: }
310:
311:
1.2 ! kristaps 312: int
! 313: mdoc_argv(struct mdoc *mdoc, int tok,
! 314: struct mdoc_arg *v, int *pos, char *buf)
! 315: {
! 316: int i, ppos;
! 317: char *argv;
! 318:
! 319: (void)memset(v, 0, sizeof(struct mdoc_arg));
! 320:
! 321: if (0 == buf[*pos])
! 322: return(0);
! 323:
! 324: assert( ! isspace(buf[*pos]));
! 325:
! 326: if ('-' != buf[*pos]) {
! 327: (void)mdoc_err(mdoc, tok, *pos, ERR_SYNTAX_ARGFORM);
! 328: return(-1);
! 329: }
! 330:
! 331: i = *pos;
! 332: argv = &buf[++(*pos)];
! 333:
! 334: while (buf[*pos] && ! isspace(buf[*pos]))
! 335: (*pos)++;
! 336:
! 337: if (buf[*pos])
! 338: buf[(*pos)++] = 0;
! 339:
! 340: if (MDOC_ARG_MAX == (v->arg = lookup(tok, argv))) {
! 341: (void)mdoc_err(mdoc, tok, i, ERR_SYNTAX_ARG);
! 342: return(-1);
! 343: }
! 344:
! 345: while (buf[*pos] && isspace(buf[*pos]))
! 346: (*pos)++;
! 347:
! 348: /* FIXME: whitespace if no value. */
! 349:
! 350: ppos = *pos;
! 351: if ( ! parse(mdoc, tok, v, pos, buf))
! 352: return(-1);
! 353: if ( ! postparse(mdoc, tok, v, ppos))
! 354: return(-1);
! 355:
! 356: return(1);
! 357: }
! 358:
! 359:
1.1 kristaps 360: void
361: mdoc_argv_free(int sz, struct mdoc_arg *arg)
362: {
363: int i;
364:
365: for (i = 0; i < sz; i++) {
366: if (0 == arg[i].sz) {
367: assert(NULL == arg[i].value);
368: continue;
369: }
370: assert(arg[i].value);
371: free(arg[i].value);
372: }
373: }
1.2 ! kristaps 374:
CVSweb