Annotation of embedaddon/confuse/src/lexer.l, revision 1.1
1.1 ! misho 1: %{
! 2: /*
! 3: * Copyright (c) 2002,2003,2007 Martin Hedenfalk <martin@bzero.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 above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17:
! 18: #ifdef HAVE_CONFIG_H
! 19: # include <config.h>
! 20: #endif
! 21:
! 22: #include <assert.h>
! 23:
! 24: #ifdef HAVE_STRING_H
! 25: # include <string.h>
! 26: #endif
! 27: #include "confuse.h"
! 28:
! 29: #include <errno.h>
! 30:
! 31: #if defined(ENABLE_NLS) && defined(HAVE_GETTEXT)
! 32: # include <libintl.h>
! 33: # define _(str) dgettext(PACKAGE, str)
! 34: #else
! 35: # define _(str) str
! 36: #endif
! 37: #define N_(str) str
! 38:
! 39: /*
! 40: * Prevent compilation of static input() function in generated code
! 41: * This function is never used but GCC 4.3 will warn about it.
! 42: */
! 43: #define YY_NO_INPUT
! 44:
! 45: typedef char * YYSTYPE;
! 46: extern YYSTYPE cfg_yylval;
! 47:
! 48: #define YY_DECL int cfg_yylex ( cfg_t *cfg )
! 49:
! 50: /* temporary buffer for the quoted strings scanner
! 51: */
! 52: char *cfg_qstring = NULL;
! 53: static unsigned int qstring_index = 0;
! 54: static unsigned int qstring_len = 0;
! 55: static void qputc(char ch);
! 56: #define CFG_QSTRING_BUFSIZ 32
! 57:
! 58: #define MAX_INCLUDE_DEPTH 10
! 59: struct {
! 60: YY_BUFFER_STATE state;
! 61: char *filename;
! 62: unsigned int line;
! 63: } cfg_include_stack[MAX_INCLUDE_DEPTH];
! 64: int cfg_include_stack_ptr = 0;
! 65:
! 66: static YY_BUFFER_STATE pre_string_scan_state = 0;
! 67: static YY_BUFFER_STATE string_scan_state = 0;
! 68:
! 69: %}
! 70:
! 71: %option noyywrap
! 72:
! 73: /* start conditions
! 74: */
! 75: %x comment
! 76: %x dq_str
! 77: %x sq_str
! 78:
! 79: %%
! 80:
! 81: [ \t]+ /* eat up whitespace */
! 82:
! 83: \n cfg->line++; /* keep track of line number */
! 84:
! 85: ("#"|"//")[^\n]* /* eat up one-line comments */
! 86:
! 87: /* special keywords/symbols
! 88: */
! 89: "{" { cfg_yylval = yytext; return '{'; }
! 90: "}" { cfg_yylval = yytext; return '}'; }
! 91: "(" { cfg_yylval = yytext; return '('; }
! 92: ")" { cfg_yylval = yytext; return ')'; }
! 93: "=" { cfg_yylval = yytext; return '='; }
! 94: "+=" { cfg_yylval = yytext; return '+'; }
! 95: "," { cfg_yylval = yytext; return ','; }
! 96:
! 97: /* handle multi-line C-style comments
! 98: */
! 99: "/*" BEGIN(comment);
! 100: <comment>[^*\n]* /* eat anything that's not a '*' */
! 101: <comment>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
! 102: <comment>\n cfg->line++;
! 103: <comment>"*"+"/" BEGIN(INITIAL);
! 104:
! 105: /* handle C-style strings
! 106: */
! 107: "\"" {
! 108: qstring_index = 0;
! 109: BEGIN(dq_str);
! 110: }
! 111: <dq_str>\" { /* saw closing quote - all done */
! 112: BEGIN(INITIAL);
! 113: qputc('\0');
! 114: cfg_yylval = cfg_qstring;
! 115: return CFGT_STR;
! 116: }
! 117: <dq_str>$\{[^}]*\} { /* environment variable substitution */
! 118: char *var;
! 119: char *e;
! 120: yytext[strlen(yytext) - 1] = 0;
! 121: e = strchr(yytext+2, ':');
! 122: if(e && e[1] == '-')
! 123: *e = 0;
! 124: else
! 125: e = 0;
! 126: var = getenv(yytext+2);
! 127: if(!var && e)
! 128: var = e+2;
! 129: while(var && *var)
! 130: qputc(*var++);
! 131: }
! 132: <dq_str>\n {
! 133: qputc('\n');
! 134: cfg->line++;
! 135: }
! 136: <dq_str>\\\n { /* allow continuing on next line */
! 137: /* no-op */
! 138: cfg->line++;
! 139: }
! 140: <dq_str>\\[0-7]{1,3} { /* octal escape sequence */
! 141: unsigned int result;
! 142: sscanf(yytext + 1, "%o", &result);
! 143: if(result > 0xFF) {
! 144: cfg_error(cfg, _("invalid octal number '%s'"), yytext);
! 145: return 0;
! 146: }
! 147: qputc(result);
! 148: }
! 149: <dq_str>\\[0-9]+ {
! 150: cfg_error(cfg, _("bad escape sequence '%s'"), yytext);
! 151: return 0;
! 152: }
! 153: <dq_str>"\\x"[0-9A-Fa-f]{1,2} { /* hexadecimal escape sequence */
! 154: unsigned int result;
! 155: sscanf(yytext + 2, "%x", &result);
! 156: qputc(result);
! 157: }
! 158: <dq_str>\\n {
! 159: qputc('\n');
! 160: }
! 161: <dq_str>\\r {
! 162: qputc('\r');
! 163: }
! 164: <dq_str>\\b {
! 165: qputc('\b');
! 166: }
! 167: <dq_str>\\f {
! 168: qputc('\f');
! 169: }
! 170: <dq_str>\\a {
! 171: qputc('\007');
! 172: }
! 173: <dq_str>\\e {
! 174: qputc('\033');
! 175: }
! 176: <dq_str>\\t {
! 177: qputc('\t');
! 178: }
! 179: <dq_str>\\v {
! 180: qputc('\v');
! 181: }
! 182: <dq_str>\\. {
! 183: qputc(yytext[1]);
! 184: }
! 185: <dq_str>[^\\\"\n]+ {
! 186: char *yptr = yytext;
! 187: while(*yptr) {
! 188: qputc(*yptr++);
! 189: }
! 190: }
! 191:
! 192: /* single-quoted string ('...') */
! 193: "\'" {
! 194: qstring_index = 0;
! 195: BEGIN(sq_str);
! 196: }
! 197: <sq_str>\' { /* saw closing quote - all done */
! 198: BEGIN(INITIAL);
! 199: qputc('\0');
! 200: cfg_yylval = cfg_qstring;
! 201: return CFGT_STR;
! 202: }
! 203: <sq_str>\n {
! 204: qputc('\n');
! 205: cfg->line++;
! 206: }
! 207: <sq_str>\\\n { /* allow continuing on next line */
! 208: /* no-op */
! 209: cfg->line++;
! 210: }
! 211: <sq_str>\\[\\\'] {
! 212: qputc(yytext[1]);
! 213: }
! 214: <sq_str>\\[^\\\'] {
! 215: qputc(yytext[0]);
! 216: qputc(yytext[1]);
! 217: }
! 218: <sq_str>[^\\\'\n]+ {
! 219: char *cp = yytext;
! 220: while(*cp != '\0') {
! 221: qputc(*cp++);
! 222: }
! 223: }
! 224: <sq_str><<EOF>> {
! 225: cfg_error(cfg, _("unterminated string constant"));
! 226: return 0;
! 227: }
! 228:
! 229: <<EOF>> {
! 230: if (cfg_include_stack_ptr <= 0)
! 231: {
! 232: return EOF;
! 233: }
! 234: else
! 235: {
! 236: yy_delete_buffer( YY_CURRENT_BUFFER );
! 237: fclose(cfg_yyin);
! 238: cfg_yyin = 0;
! 239: --cfg_include_stack_ptr;
! 240: yy_switch_to_buffer(
! 241: cfg_include_stack[cfg_include_stack_ptr].state );
! 242: free(cfg->filename);
! 243: cfg->filename = cfg_include_stack[cfg_include_stack_ptr].filename;
! 244: cfg->line = cfg_include_stack[cfg_include_stack_ptr].line;
! 245: }
! 246: }
! 247:
! 248: $\{[^}]*\} {
! 249: char *var;
! 250: char *e;
! 251: yytext[strlen(yytext) - 1] = 0;
! 252: e = strchr(yytext+2, ':');
! 253: if(e && e[1] == '-')
! 254: *e = 0;
! 255: else
! 256: e = 0;
! 257: var = getenv(yytext+2);
! 258: if(!var && e)
! 259: var = e+2;
! 260: if(!var)
! 261: var = "";
! 262: cfg_yylval = var;
! 263: return CFGT_STR;
! 264: }
! 265:
! 266: /* an unquoted string
! 267: * a slash can't be followed by another slash (c++
! 268: * comment) or an asterisk (C multi-line comment)
! 269: */
! 270: (\/[^ #\"\'\t\n\r={}()+,\/*]|[^ #\"\'\t\n\r={}()+,\*])+ {
! 271: cfg_yylval = yytext;
! 272: return CFGT_STR;
! 273: }
! 274:
! 275: . /* eat any non-matching characters */
! 276:
! 277: %%
! 278:
! 279: void cfg_dummy_function(void)
! 280: {
! 281: /* please compiler :-)
! 282: * otherwise "defined but not used" warning
! 283: */
! 284: yyunput(0, 0);
! 285: }
! 286:
! 287: int cfg_lexer_include(cfg_t *cfg, const char *filename)
! 288: {
! 289: char *xfilename;
! 290:
! 291: if(cfg_include_stack_ptr >= MAX_INCLUDE_DEPTH) {
! 292: cfg_error(cfg, _("includes nested too deeply"));
! 293: return 1;
! 294: }
! 295:
! 296: cfg_include_stack[cfg_include_stack_ptr].state = YY_CURRENT_BUFFER;
! 297: cfg_include_stack[cfg_include_stack_ptr].filename = cfg->filename;
! 298: cfg_include_stack[cfg_include_stack_ptr].line = cfg->line;
! 299: cfg_include_stack_ptr++;
! 300:
! 301: xfilename = cfg_tilde_expand(filename);
! 302:
! 303: cfg_yyin = fopen(xfilename, "r");
! 304:
! 305: if(!cfg_yyin) {
! 306: cfg_error(cfg, "%s: %s", xfilename, strerror(errno));
! 307: free(xfilename);
! 308: return 1;
! 309: }
! 310:
! 311: cfg->filename = xfilename;
! 312: cfg->line = 1;
! 313:
! 314: yy_switch_to_buffer(yy_create_buffer(cfg_yyin, YY_BUF_SIZE));
! 315: return 0;
! 316: }
! 317:
! 318: /* write a character to the quoted string buffer, and reallocate as
! 319: * necessary
! 320: */
! 321: static void qputc(char ch)
! 322: {
! 323: if(qstring_index >= qstring_len) {
! 324: qstring_len += CFG_QSTRING_BUFSIZ;
! 325: cfg_qstring = (char *)realloc(cfg_qstring, qstring_len);
! 326: assert(cfg_qstring);
! 327: memset(cfg_qstring + qstring_index, 0, CFG_QSTRING_BUFSIZ);
! 328: }
! 329: cfg_qstring[qstring_index++] = ch;
! 330: }
! 331:
! 332: void cfg_scan_string_begin(const char *buf)
! 333: {
! 334: pre_string_scan_state = YY_CURRENT_BUFFER;
! 335:
! 336: /* yy_scan_string does a yy_switch_to_buffer call for us
! 337: */
! 338: string_scan_state = yy_scan_string(buf);
! 339: }
! 340:
! 341: void cfg_scan_string_end(void)
! 342: {
! 343: /* restore to previous state
! 344: */
! 345: yy_delete_buffer(string_scan_state);
! 346: if (pre_string_scan_state)
! 347: yy_switch_to_buffer(pre_string_scan_state);
! 348: free(cfg_qstring);
! 349: cfg_qstring = 0;
! 350: qstring_index = qstring_len = 0;
! 351: string_scan_state = 0;
! 352: }
! 353:
! 354: static YY_BUFFER_STATE pre_fp_scan_state;
! 355: static YY_BUFFER_STATE fp_scan_state;
! 356:
! 357: void cfg_scan_fp_begin(FILE *fp)
! 358: {
! 359: pre_fp_scan_state = YY_CURRENT_BUFFER;
! 360: fp_scan_state = yy_create_buffer(fp, YY_BUF_SIZE);
! 361: yy_switch_to_buffer(fp_scan_state);
! 362: }
! 363:
! 364: void cfg_scan_fp_end(void)
! 365: {
! 366: /* restore to previous state
! 367: */
! 368: yy_delete_buffer(fp_scan_state);
! 369: if(pre_fp_scan_state)
! 370: yy_switch_to_buffer(pre_fp_scan_state);
! 371: free(cfg_qstring);
! 372: cfg_qstring = 0;
! 373: qstring_index = qstring_len = 0;
! 374: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>