1/**
2 * Copyright (C) 1999-2007  Free Software Foundation, Inc.
3 *
4 * This file is part of GNU gengetopt
5 *
6 * GNU gengetopt is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3, or (at your option)
9 * any later version.
10 *
11 * GNU gengetopt is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14 * Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with gengetopt; see the file COPYING. If not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21
22%{
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include <string.h>
28#include <sstream>
29
30#include "argsdef.h"
31#include "parser.h"
32extern int gengetopt_count_line;
33
34static void update_count_line (char *str);
35static void updateTokenInfo (int pos);
36
37// the buffer for strings (possibly spanning more lines)
38static std::ostringstream buff;
39
40static void buffer(const char *s);
41static char *flush_buffer();
42
43#define LINEBUF_LEN 1024
44
45#define PUSH(s) yy_push_state(s);
46#define POP() yy_pop_state();
47
48int tokenpos = 0;
49char linebuf[LINEBUF_LEN] ; /* current line */
50
51//#define DEBUG_SCANNER
52#ifdef DEBUG_SCANNER
53#include <iostream> // for debug
54#define DEB(s) std::cerr << s << std::endl;
55#define DEB2(s,s2) std::cerr << s << ": " << s2 << std::endl;
56#else
57#define DEB(s)
58#define DEB2(s,s2)
59#endif
60
61%}
62
63%option stack nomain yylineno noyywrap nounput
64
65ws [ ]+
66tabs [\t]+
67
68%s SIZE_STATE STRING_STATE
69
70%%
71
72
73<INITIAL>string		updateTokenInfo (-1); yylval.argtype = ARG_STRING; return TOK_ARGTYPE;
74<INITIAL>int		updateTokenInfo (-1); yylval.argtype = ARG_INT; return TOK_ARGTYPE;
75<INITIAL>short		updateTokenInfo (-1); yylval.argtype = ARG_SHORT; return TOK_ARGTYPE;
76<INITIAL>long		updateTokenInfo (-1); yylval.argtype = ARG_LONG; return TOK_ARGTYPE;
77<INITIAL>float		updateTokenInfo (-1); yylval.argtype = ARG_FLOAT; return TOK_ARGTYPE;
78<INITIAL>double		updateTokenInfo (-1); yylval.argtype = ARG_DOUBLE; return TOK_ARGTYPE;
79<INITIAL>longdouble	updateTokenInfo (-1); yylval.argtype = ARG_LONGDOUBLE; return TOK_ARGTYPE;
80<INITIAL>longlong	updateTokenInfo (-1); yylval.argtype = ARG_LONGLONG; return TOK_ARGTYPE;
81<INITIAL>enum		updateTokenInfo (-1); yylval.argtype = ARG_ENUM; return TOK_ARGTYPE;
82
83<INITIAL>package        	updateTokenInfo (-1); return TOK_PACKAGE;
84<INITIAL>version        	updateTokenInfo (-1); return TOK_VERSION;
85<INITIAL>groupoption     updateTokenInfo (-1); yylloc.first_line = gengetopt_count_line; return TOK_GROUPOPTION;
86<INITIAL>modeoption     updateTokenInfo (-1); yylloc.first_line = gengetopt_count_line; return TOK_MODEOPTION;
87<INITIAL>yes|required    updateTokenInfo (-1); return TOK_YES;
88<INITIAL>no|optional	updateTokenInfo (-1); return TOK_NO;
89<INITIAL>option		updateTokenInfo (-1); yylloc.first_line = gengetopt_count_line; return TOK_OPTION;
90<INITIAL>flag		updateTokenInfo (-1); return TOK_FLAG;
91<INITIAL>on	        updateTokenInfo (-1); return TOK_ON;
92<INITIAL>off	        updateTokenInfo (-1); return TOK_OFF;
93<INITIAL>purpose	updateTokenInfo (-1); return TOK_PURPOSE;
94<INITIAL>description	updateTokenInfo (-1); return TOK_DESCRIPTION;
95<INITIAL>usage		updateTokenInfo (-1); return TOK_USAGE;
96<INITIAL>default	updateTokenInfo (-1); return TOK_DEFAULT;
97<INITIAL>typestr	updateTokenInfo (-1); return TOK_TYPESTR;
98<INITIAL>group		updateTokenInfo (-1); return TOK_GROUP;
99<INITIAL>groupdesc	updateTokenInfo (-1); return TOK_GROUPDESC;
100<INITIAL>defgroup	updateTokenInfo (-1); return TOK_DEFGROUP;
101<INITIAL>mode		updateTokenInfo (-1); return TOK_MODE;
102<INITIAL>modedesc	updateTokenInfo (-1); return TOK_MODEDESC;
103<INITIAL>defmode	updateTokenInfo (-1); return TOK_DEFMODE;
104<INITIAL>multiple	updateTokenInfo (-1); return TOK_MULTIPLE;
105<INITIAL>argoptional	updateTokenInfo (-1); return TOK_ARGOPTIONAL;
106<INITIAL>sectiondesc     updateTokenInfo (-1); return TOK_SECTIONDESC;
107<INITIAL>section         updateTokenInfo (-1); return TOK_SECTION;
108<INITIAL>values          updateTokenInfo (-1); return TOK_VALUES;
109<INITIAL>hidden		updateTokenInfo (-1); return TOK_HIDDEN;
110<INITIAL>dependon	updateTokenInfo (-1); return TOK_DEPENDON;
111<INITIAL>details	updateTokenInfo (-1); return TOK_DETAILS;
112<INITIAL>text    	updateTokenInfo (-1); return TOK_TEXT;
113<INITIAL>versiontext	updateTokenInfo (-1); return TOK_VERSIONTEXT;
114<INITIAL>args    	updateTokenInfo (-1); return TOK_ARGS;
115
116<INITIAL>"=" { updateTokenInfo (-1); return '='; }
117<INITIAL>"," { updateTokenInfo (-1); return ','; }
118
119<INITIAL>"(" { PUSH(SIZE_STATE); updateTokenInfo (-1); return '('; }
120<SIZE_STATE>"-" { updateTokenInfo (-1); return '-'; }
121<SIZE_STATE>[[:digit:]]+ { updateTokenInfo (-1); yylval.str = strdup(yytext); return TOK_SIZE; }
122<SIZE_STATE>")" { POP(); updateTokenInfo (-1); return ')'; }
123
124<INITIAL>[[:alnum:]-]|\?	 updateTokenInfo (-1); yylval.chr = yytext[0]; return TOK_CHAR;
125
126<INITIAL>\" { updateTokenInfo (-1); DEB("start string"); PUSH(STRING_STATE) ; }
127<STRING_STATE>\\\\n { updateTokenInfo (2); buffer("\\\\n"); }
128<STRING_STATE>\\n { updateTokenInfo (1); buffer("\n"); }
129<STRING_STATE>\n+ {  update_count_line (yytext); buffer( yytext ) ; }
130<STRING_STATE>\\{ws}*\n { update_count_line (yytext); /* a line break */ }
131<STRING_STATE>\\\" { updateTokenInfo (-1); buffer(yytext); }
132<STRING_STATE>\" { updateTokenInfo (-1); DEB("end string"); POP() ; yylval.str = flush_buffer(); return TOK_STRING; }
133<STRING_STATE>[^\n] {  updateTokenInfo (-1); buffer( yytext ) ; }
134
135<INITIAL>{ws}           updateTokenInfo (-1);
136<INITIAL>{tabs}         updateTokenInfo (8*yyleng);
137
138<INITIAL,SIZE_STATE>#[^\n]*	/* comments begin with # in any place (but strings) */
139<INITIAL>\n.*		update_count_line (0); yyless(1) ; /* give back all but the \n to rescan */
140
141\r              {}
142
143.		{
144  return 1000; /* little hack to produce a parse error too. */
145}
146
147%%
148
149#pragma GCC diagnostic push
150#pragma GCC diagnostic ignored "-Wunused-function"
151static void suppress_unused_function_warning_for_yy_top_state(void)
152{
153	(void)yy_top_state;
154}
155#pragma GCC diagnostic pop
156
157/*
158  Otherwise '\n' within a TOK_MLSTRING would not be counted
159*/
160void
161update_count_line (char *str)
162{
163  if (str)
164    {
165      char *p;
166      for (p = str; *p; ++p)
167        if (*p == '\n') {
168          ++gengetopt_count_line;
169          tokenpos = 0 ; /* reset token position */
170          strncpy (linebuf, ( (p+1) ? p+1 : ""), LINEBUF_LEN - 1);
171        }
172    }
173  else
174    {
175      ++gengetopt_count_line;
176      tokenpos = 0 ; /* reset token position */
177      strncpy (linebuf, yytext+1, LINEBUF_LEN - 1); /* save the next line */
178    }
179}
180
181void
182updateTokenInfo( int pos )
183{
184  if ( pos >= 0 )
185    tokenpos += pos ;
186  else
187    tokenpos += yyleng ;
188}
189
190void buffer(const char *s)
191{
192  buff << s;
193}
194
195char *flush_buffer()
196{
197  char *ret = strdup(buff.str().c_str());
198  buff.str("");
199  return ret;
200}
201