/*- * Copyright (c) 1997, 1998, 2003 * LEMIS Pty Ltd. * * This software is distributed under the so-called ``Berkeley * License'': * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * This software is provided ``as is'', and any express or implied * warranties, including, but not limited to, the implied warranties of * merchantability and fitness for a particular purpose are disclaimed. * In no event shall the company or contributors be liable for any * direct, indirect, incidental, special, exemplary, or consequential * damages (including, but not limited to, procurement of substitute * goods or services; loss of use, data, or profits; or business * interruption) however caused and on any theory of liability, whether * in contract, strict liability, or tort (including negligence or * otherwise) arising in any way out of the use of this software, even if * advised of the possibility of such damage. * * $Id: parser.c,v 1.2 2004/07/10 01:23:32 grog Exp $ */ /* * Go through a text and split up into text tokens. These are either non-blank * sequences, or any sequence (except \0) enclosed in ' or ". Embedded ' or * " characters may be escaped by \, which otherwise has no special meaning. * * Delimit by following with a \0, and return pointers to the starts at token []. * Return the number of tokens found as the return value. * * This method has the restriction that a closing " or ' must be followed by * grey space. * * Error conditions are end of line before end of quote, or no space after * a closing quote. In this case, tokenize() returns -1. */ #ifdef FREEBSD #include #endif #include #include #include #include #include #include "main.h" /* * Our complete vocabulary. The names of the commands are * the same as the identifier without the kw_ at the beginning * (i.e. kw_create defines the "create" keyword). Preprocessor * magic in parser.c does the rest. * * To add a new word: put it in the table below and one of the * lists in parser.c (probably keywords). */ struct _keywords keywords []; struct keywordset keyword_set; /* Parser functions */ enum keyword get_keyword (char *, struct keywordset *); int tokenize (char *, char * [], int); /* List of keywords */ #include "parserc.h" struct keywordset keyword_set = KEYWORDSET (keywords); #if 0 /* XXX complete this. We should generate code for this stuff */ struct _keywords flag_keywords [] = { flagkeypair (f), flagkeypair (d), flagkeypair (v), flagkeypair (s), flagkeypair (r), flagkeypair (w) }; struct keywordset flag_set = KEYWORDSET (flag_keywords); #endif /* * Take a blank separated list of tokens and turn it into a list of * individual nul-delimited strings. Build a list of pointers at * token, which must have enough space for the tokens. Return the * number of tokens, or -1 on error (typically a missing string * delimiter). */ int tokenize (char *cptr, char *token [], int maxtoken) { char delim; /* delimiter for searching for the partner */ int tokennr; /* index of this token */ for (tokennr = 0; tokennr < maxtoken; ) { while (isspace (*cptr)) cptr++; /* skip initial white space */ if ((*cptr == '\0') || (*cptr == '\n') || (*cptr == '#')) /* end of line */ return tokennr; /* return number of tokens found */ delim = *cptr; token [tokennr] = cptr; /* point to it */ tokennr++; /* one more */ if (tokennr == maxtoken) /* run off the end? */ return tokennr; #ifdef XXX /* XXX this is broken. It leaves superfluous \\ characters in the text */ #endif if ((delim == '\'') || (delim == '"')) /* delimitered */ { for (;;) { cptr++; if ((*cptr == delim) && (cptr [-1] != '\\')) /* found the partner */ { cptr++; /* move on past */ if (! isspace (*cptr)) /* error, no space after closing quote */ return -1; *cptr++ = '\0'; /* delimit */ } else if ((*cptr == '\0') || (*cptr == '\n')) /* end of line */ return -1; } } else /* not quoted */ { while ((*cptr != '\0') && (! isspace (*cptr)) && (*cptr != '\n')) cptr++; if (*cptr != '\0') /* not end of the line, */ *cptr++ = '\0'; /* delimit and move to the next */ } } return maxtoken; /* can't get here */ } /* Find a keyword and return an index */ enum keyword get_keyword (char *name, struct keywordset *keywordset) { int i; struct _keywords *keywords = keywordset->k; /* point to the keywords */ if (name != NULL) /* parameter exists */ { for (i = 0; i < keywordset->size; i++) if (! strcmp (name, keywords [i].name)) return (enum keyword) keywords [i].keyword; } return kw_invalid_keyword; }