diff options
Diffstat (limited to 'macro.c')
-rw-r--r-- | macro.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/macro.c b/macro.c new file mode 100644 index 00000000..722b2996 --- /dev/null +++ b/macro.c @@ -0,0 +1,105 @@ +/* $Id$ */ +/* + * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +#include <stdlib.h> + +#include "roff.h" + +static int +macro_args_next(struct rofftree *tree, int *pos, char *buf, char **v) +{ + int i; + + if (0 == buf[*pos]) + return(0); + + if ('\"' == buf[*pos]) { + /* Syntax error: quotation marks not allowed. */ + return(-1); + } + + *v = &buf[*pos]; + + while (buf[*pos] && ! isspace(buf[*pos])) + (*pos)++; + + if (buf[*pos + 1] && '\\' == buf[*pos]) { + /* Syntax error: escaped whitespace not allowed. */ + return(-1); + } + + buf[i] = 0; + return(1); +} + +/* + * Parses the following: + * + * .Xx foo bar baz ; foo "bar baz" ; ; + * ^---------- ^---------- + */ +static int +macro_fl(struct rofftree *tree, int tok, int *pos, char *buf) +{ + int i, j, c, first; + char *args[ROFF_MAXLINEARG]; + + first = *pos == 0; + + for (j = 0; ; ) { + i = *pos; + c = macro_args_next(tree, *i, buf, args[j]); + if (-1 == c) + return(0); + if (0 == c) + break; + + /* Break at the next command. */ + + if (ROFF_MAX != (c = rofffindcallable(args[pos]))) { + if ( ! macro(tree, tok, argc, argv, i, p)) + return(0); + if ( ! parse(tree, c, pos, args)) + return(0); + break; + } + + /* Continue if we're just words. */ + + if ( ! roffispunct(args[pos])) { + i++; + continue; + } + + /* Break if there's only remaining punctuation. */ + + if (args[pos + 1] && roffispunct(args[pos + 1])) + break; + + /* If there are remaining words, start anew. */ + + if ( ! macro(tree, tok, argc, argv, i, p)) + return(0); + + /* Spit out the punctuation. */ + + if ( ! word(tree, tok, *args++)) + return(0); + i++; + } +} |