%{ /* ** Copyright (C) 2006-2007 by Carnegie Mellon University. ** ** @OPENSOURCE_HEADER_START@ ** ** Use of the SILK system and related source code is subject to the terms ** of the following licenses: ** ** GNU Public License (GPL) Rights pursuant to Version 2, June 1991 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.225-7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract F19628-00-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ */ /* ** Tokenizer for silk toolset configuration file. ** */ #include "silk.h" RCSIDENT("$SiLK: sksiteconfig_lex.l 7569 2007-06-18 16:08:47Z mthomas $"); #include "sksiteconfig.h" #include "sksiteconfig_parse.h" #include "utils.h" typedef struct _sksiteconfig_includes { YY_BUFFER_STATE state; char *name; FILE *fp; int line; } sksiteconfig_file_t; /* EXPORTED VARIABLES */ /* LOCAL VARIABLES */ /* count the number of errors that have occurred during processing */ static int sksiteconfig_errors = 0; /* support for "include" */ static sksiteconfig_file_t sksiteconfig_stack[SKSITECONFIG_MAX_INCLUDE_DEPTH]; /* next stack position */ static int sksiteconfig_stack_depth = 0; /* current pointer into sksiteconfig_stack[] */ static sksiteconfig_file_t *sksiteconfig_file = NULL; /* local buffer for reading quoted strings */ #define BUF_SIZE 2048 static char sksiteconfig_buf[BUF_SIZE]; static char *sksiteconfig_buf_end = sksiteconfig_buf + BUF_SIZE - 1; static char *sksiteconfig_buf_ptr; /* Macros for checking that we're not overflowing the buffer, returning * a string, and appending a single character to a string. */ #define STRING_CHECK \ if ( sksiteconfig_buf_ptr >= sksiteconfig_buf_end ) { \ BEGIN(ST_ERR); \ return ERR_STR_TOO_LONG; \ } #define STRING_RETURN \ sksiteconfig_buf_ptr = '\0'; \ yylval.str = strdup(sksiteconfig_buf); \ return TOK_STRING; #define STRING_APPEND(x) (*sksiteconfig_buf_ptr++ = (x)) /* To avoid warnings with flex */ #define YY_NO_UNPUT 1 %} %option prefix="sksiteconfig_" outfile="lex.yy.c" /* The INITIAL state is used for top-level commands */ /* The ST_ARGS state is for processing arguments to commands */ %s ST_ARGS /* The ST_ERR state is for error recovery, ignores everything to EOL */ %s ST_ERR /* The ST_STRING state is for consuming quoted strings */ %s ST_STRING /* Whitespace (to be ignored */ ws [ \t\r]+ /* Atoms (symbols) without quotes */ atomchar [-._/@A-Za-z0-9] atom {atomchar}+ /* Integral numbers (value returned to parser as a string) */ digit [0-9] integer {digit}+ /* End of line: command separator */ nl \n %% /* INITIAL state: Throw away comments, whitespace. Treat any atom as a command name, plus "end ". Valid commands are returned as specific tokens. Unknown commands are returned as strings for error reporting purposes. Anything else implies the whole line cannot be interpreted, and enters the ST_ERR state to clear out everything to the EOL. After a valid command, enter the ST_ARGS state for argument parsing. */ {ws} ; #.*\n { ++sksiteconfig_file->line; return TOK_NL; } \n { ++sksiteconfig_file->line; return TOK_NL; } class { BEGIN(ST_ARGS); return TOK_CLASS; } default-class { BEGIN(ST_ARGS); return TOK_DEF_CLASS; } default-types { BEGIN(ST_ARGS); return TOK_DEF_TYPES; } end{ws}class { BEGIN(ST_ARGS); return TOK_END_CLASS; } end{ws}group { BEGIN(ST_ARGS); return TOK_END_GROUP; } end{ws}{atom} { yylval.str = strdup(yytext); BEGIN(ST_ERR); return ERR_UNK_CMD; } group { BEGIN(ST_ARGS); return TOK_GROUP; } include { BEGIN(ST_ARGS); return TOK_INCLUDE; } path-format { BEGIN(ST_ARGS); return TOK_PATH_FORMAT; } sensor { BEGIN(ST_ARGS); return TOK_SENSOR; } sensors { BEGIN(ST_ARGS); return TOK_SENSORS; } type { BEGIN(ST_ARGS); return TOK_TYPE; } version { BEGIN(ST_ARGS); return TOK_VERSION; } {atom} { yylval.str = strdup(yytext); BEGIN(ST_ERR); return ERR_UNK_CMD; } . { BEGIN(ST_ERR); return ERR_UNREC; } /* ST_ERR state: Throw away everything up to the newline, because we've seen something we're unable to interpret. */ .*\n { BEGIN(INITIAL); ++sksiteconfig_file->line; return TOK_NL; } /* ST_ARGS state: Ignore whitespace as usual, at a newline or comment, return back to the INITIAL state. Atoms, integers, and quoted strings are all valid input in this state. */ {ws} ; #.*\n { BEGIN(INITIAL); ++sksiteconfig_file->line; return TOK_NL; } \n { BEGIN(INITIAL); ++sksiteconfig_file->line; return TOK_NL; } {integer} { yylval.str = strdup(yytext); return TOK_INTEGER; } {atom} { yylval.str = strdup(yytext); return TOK_ATOM; } \" { BEGIN(ST_STRING); sksiteconfig_buf_ptr = sksiteconfig_buf; } . { BEGIN(ST_ERR); return ERR_UNREC; } /* ST_STRING state: Accepts the remainder of a quoted string (after the initial quote) and returns the value. This is pretty much equivalent to quoted strings in C. */ \" { BEGIN(ST_ARGS); STRING_CHECK; *sksiteconfig_buf_ptr = '\0'; yylval.str = strdup(sksiteconfig_buf); return TOK_STRING; } \n { BEGIN(INITIAL); ++sksiteconfig_file->line; return ERR_UNTERM_STRING; } \\[0-7]{1,3} { int oct_char; STRING_CHECK; (void) sscanf(yytext+1, "%o", &oct_char); if ( oct_char > 0xff ) { BEGIN(ST_ERR); return ERR_INVALID_OCTAL_ESCAPE; }; *sksiteconfig_buf_ptr++ = oct_char; } \\[0-9]+ { BEGIN(ST_ERR); return ERR_INVALID_OCTAL_ESCAPE; } \\n { STRING_CHECK; *sksiteconfig_buf_ptr++ = '\n'; } \\t { STRING_CHECK; *sksiteconfig_buf_ptr++ = '\t'; } \\r { STRING_CHECK; *sksiteconfig_buf_ptr++ = '\r'; } \\b { STRING_CHECK; *sksiteconfig_buf_ptr++ = '\b'; } \\f { STRING_CHECK; *sksiteconfig_buf_ptr++ = '\f'; } \\\n { STRING_CHECK; *sksiteconfig_buf_ptr++ = '\n'; } \\. { STRING_CHECK; *sksiteconfig_buf_ptr++ = yytext[1]; } [^\\\n\"]+ { if ( (sksiteconfig_buf_ptr + yyleng) > sksiteconfig_buf_end ) { BEGIN(ST_ERR); return ERR_STR_TOO_LONG; }; memcpy(sksiteconfig_buf_ptr, yytext, yyleng); sksiteconfig_buf_ptr += yyleng; } %% int yywrap(void) { return sksiteconfigIncludePop(); } /* Report an error while parsing (printf style) */ #ifndef sksiteconfigErr void sksiteconfigErr(const char *fmt, ...) { va_list ap; va_start(ap, fmt); fprintf(stderr, "%s: ", skAppName()); vfprintf(stderr, fmt, ap); if (sksiteconfig_file != NULL && sksiteconfig_file->name != NULL) { fprintf(stderr, " at %s:%d", sksiteconfig_file->name, sksiteconfig_file->line); } fprintf(stderr, "\n"); sksiteconfig_errors++; va_end(ap); } #endif /* sksiteconfigErr() */ int sksiteconfigIncludePop(void) { /* if depth is 0, we are done */ if ( sksiteconfig_stack_depth == 0 ) { return 1; } /* clean up current state */ yy_delete_buffer(YY_CURRENT_BUFFER); fclose(sksiteconfig_file->fp); free(sksiteconfig_file->name); /* go to the previous state; if depth is 0, we are done */ --sksiteconfig_stack_depth; if ( sksiteconfig_stack_depth == 0 ) { sksiteconfig_file = NULL; return 1; } sksiteconfig_file = &(sksiteconfig_stack[sksiteconfig_stack_depth-1]); yy_switch_to_buffer(sksiteconfig_file->state); /* let processing continue */ return 0; } static int sksiteconfigOpenFile( char *filename, int verbose_error) { sksiteconfig_file_t *new_file; const char *action_name = ((sksiteconfig_stack_depth == 0) ? "read config" : "include"); if (filename == NULL) { return -1; } if (sksiteconfig_stack_depth >= SKSITECONFIG_MAX_INCLUDE_DEPTH) { sksiteconfigErr("failed to %s file '%s' (includes nested too deeply)", action_name, filename); goto ERROR; } new_file = &sksiteconfig_stack[sksiteconfig_stack_depth]; new_file->name = filename; new_file->line = 0; /* open the file */ new_file->fp = fopen(new_file->name, "r"); if ( !new_file->fp) { if (verbose_error) { int err = errno; if ( !fileExists(new_file->name)) { sksiteconfigErr("failed to %s file '%s' (file not found)", action_name, new_file->name); } else { sksiteconfigErr("failed to %s file '%s' (%s)", action_name, new_file->name, strerror(err)); } } goto ERROR; } new_file->state = yy_create_buffer(new_file->fp, YY_BUF_SIZE); yy_switch_to_buffer(new_file->state); /* success */ sksiteconfig_file = new_file; ++sksiteconfig_stack_depth; BEGIN(INITIAL); return 0; ERROR: if (filename) { free(filename); } return -1; } void sksiteconfigIncludePush(char *filename) { (void)sksiteconfigOpenFile(filename, 1); } int sksiteconfigParse(const char *filename, int verbose) { sksiteconfig_stack_depth = 0; if (sksiteconfigOpenFile(strdup(filename), verbose)) { return -1; } (void)yyparse(); if ( sksiteconfig_errors > 0 ) { return -1; } else { return 0; } } /* ** Local variables: ** mode:c ** indent-tabs-mode:nil ** c-basic-offset:4 ** End: */