/** * Copyright (C) 1999-2007 Free Software Foundation, Inc. * * This file is part of GNU gengetopt * * GNU gengetopt is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * GNU gengetopt is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with gengetopt; see the file COPYING. If not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ %{ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "argsdef.h" #include "parser.h" extern int gengetopt_count_line; static void update_count_line (char *str); static void updateTokenInfo (int pos); // the buffer for strings (possibly spanning more lines) static std::ostringstream buff; static void buffer(const char *s); static char *flush_buffer(); #define LINEBUF_LEN 1024 #define PUSH(s) yy_push_state(s); #define POP() yy_pop_state(); int tokenpos = 0; char linebuf[LINEBUF_LEN] ; /* current line */ //#define DEBUG_SCANNER #ifdef DEBUG_SCANNER #include // for debug #define DEB(s) std::cerr << s << std::endl; #define DEB2(s,s2) std::cerr << s << ": " << s2 << std::endl; #else #define DEB(s) #define DEB2(s,s2) #endif %} %option stack nomain yylineno noyywrap nounput ws [ ]+ tabs [\t]+ %s SIZE_STATE STRING_STATE %% string updateTokenInfo (-1); yylval.argtype = ARG_STRING; return TOK_ARGTYPE; int updateTokenInfo (-1); yylval.argtype = ARG_INT; return TOK_ARGTYPE; short updateTokenInfo (-1); yylval.argtype = ARG_SHORT; return TOK_ARGTYPE; long updateTokenInfo (-1); yylval.argtype = ARG_LONG; return TOK_ARGTYPE; float updateTokenInfo (-1); yylval.argtype = ARG_FLOAT; return TOK_ARGTYPE; double updateTokenInfo (-1); yylval.argtype = ARG_DOUBLE; return TOK_ARGTYPE; longdouble updateTokenInfo (-1); yylval.argtype = ARG_LONGDOUBLE; return TOK_ARGTYPE; longlong updateTokenInfo (-1); yylval.argtype = ARG_LONGLONG; return TOK_ARGTYPE; enum updateTokenInfo (-1); yylval.argtype = ARG_ENUM; return TOK_ARGTYPE; package updateTokenInfo (-1); return TOK_PACKAGE; version updateTokenInfo (-1); return TOK_VERSION; groupoption updateTokenInfo (-1); yylloc.first_line = gengetopt_count_line; return TOK_GROUPOPTION; modeoption updateTokenInfo (-1); yylloc.first_line = gengetopt_count_line; return TOK_MODEOPTION; yes|required updateTokenInfo (-1); return TOK_YES; no|optional updateTokenInfo (-1); return TOK_NO; option updateTokenInfo (-1); yylloc.first_line = gengetopt_count_line; return TOK_OPTION; flag updateTokenInfo (-1); return TOK_FLAG; on updateTokenInfo (-1); return TOK_ON; off updateTokenInfo (-1); return TOK_OFF; purpose updateTokenInfo (-1); return TOK_PURPOSE; description updateTokenInfo (-1); return TOK_DESCRIPTION; usage updateTokenInfo (-1); return TOK_USAGE; default updateTokenInfo (-1); return TOK_DEFAULT; typestr updateTokenInfo (-1); return TOK_TYPESTR; group updateTokenInfo (-1); return TOK_GROUP; groupdesc updateTokenInfo (-1); return TOK_GROUPDESC; defgroup updateTokenInfo (-1); return TOK_DEFGROUP; mode updateTokenInfo (-1); return TOK_MODE; modedesc updateTokenInfo (-1); return TOK_MODEDESC; defmode updateTokenInfo (-1); return TOK_DEFMODE; multiple updateTokenInfo (-1); return TOK_MULTIPLE; argoptional updateTokenInfo (-1); return TOK_ARGOPTIONAL; sectiondesc updateTokenInfo (-1); return TOK_SECTIONDESC; section updateTokenInfo (-1); return TOK_SECTION; values updateTokenInfo (-1); return TOK_VALUES; hidden updateTokenInfo (-1); return TOK_HIDDEN; dependon updateTokenInfo (-1); return TOK_DEPENDON; details updateTokenInfo (-1); return TOK_DETAILS; text updateTokenInfo (-1); return TOK_TEXT; versiontext updateTokenInfo (-1); return TOK_VERSIONTEXT; args updateTokenInfo (-1); return TOK_ARGS; "=" { updateTokenInfo (-1); return '='; } "," { updateTokenInfo (-1); return ','; } "(" { PUSH(SIZE_STATE); updateTokenInfo (-1); return '('; } "-" { updateTokenInfo (-1); return '-'; } [[:digit:]]+ { updateTokenInfo (-1); yylval.str = strdup(yytext); return TOK_SIZE; } ")" { POP(); updateTokenInfo (-1); return ')'; } [[:alnum:]-]|\? updateTokenInfo (-1); yylval.chr = yytext[0]; return TOK_CHAR; \" { updateTokenInfo (-1); DEB("start string"); PUSH(STRING_STATE) ; } \\\\n { updateTokenInfo (2); buffer("\\\\n"); } \\n { updateTokenInfo (1); buffer("\n"); } \n+ { update_count_line (yytext); buffer( yytext ) ; } \\{ws}*\n { update_count_line (yytext); /* a line break */ } \\\" { updateTokenInfo (-1); buffer(yytext); } \" { updateTokenInfo (-1); DEB("end string"); POP() ; yylval.str = flush_buffer(); return TOK_STRING; } [^\n] { updateTokenInfo (-1); buffer( yytext ) ; } {ws} updateTokenInfo (-1); {tabs} updateTokenInfo (8*yyleng); #[^\n]* /* comments begin with # in any place (but strings) */ \n.* update_count_line (0); yyless(1) ; /* give back all but the \n to rescan */ \r {} . { return 1000; /* little hack to produce a parse error too. */ } %% #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" static void suppress_unused_function_warning_for_yy_top_state(void) { (void)yy_top_state; } #pragma GCC diagnostic pop /* Otherwise '\n' within a TOK_MLSTRING would not be counted */ void update_count_line (char *str) { if (str) { char *p; for (p = str; *p; ++p) if (*p == '\n') { ++gengetopt_count_line; tokenpos = 0 ; /* reset token position */ strncpy (linebuf, ( (p+1) ? p+1 : ""), LINEBUF_LEN - 1); } } else { ++gengetopt_count_line; tokenpos = 0 ; /* reset token position */ strncpy (linebuf, yytext+1, LINEBUF_LEN - 1); /* save the next line */ } } void updateTokenInfo( int pos ) { if ( pos >= 0 ) tokenpos += pos ; else tokenpos += yyleng ; } void buffer(const char *s) { buff << s; } char *flush_buffer() { char *ret = strdup(buff.str().c_str()); buff.str(""); return ret; }