Merge branch 'master' into verilog-ams
[sverilog.git] / driver / cflexor.lex
blob4922f88072474cff6fe12e7cb43cd0adc39febdd
2 %option nounput
3 %option noinput
5 %{
6 /*
7  * Copyright (c) 2001 Stephen Williams (steve@icarus.com)
8  *
9  *    This source code is free software; you can redistribute it
10  *    and/or modify it in source code form under the terms of the GNU
11  *    General Public License as published by the Free Software
12  *    Foundation; either version 2 of the License, or (at your option)
13  *    any later version.
14  *
15  *    This program is distributed in the hope that it will be useful,
16  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *    GNU General Public License for more details.
19  *
20  *    You should have received a copy of the GNU General Public License
21  *    along with this program; if not, write to the Free Software
22  *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
23  */
24 #ifdef HAVE_CVS_IDENT
25 #ident "$Id: cflexor.lex,v 1.11 2007/03/22 16:08:18 steve Exp $"
26 #endif
28 # include  "cfparse.h"
29 # include  "cfparse_misc.h"
30 # include  "globals.h"
31 # include  <string.h>
33 static int comment_enter;
34 static char* trim_trailing_white(char*txt, int trim);
37  * Mostly copied from the flex manual. Do not make this arbitrary
38  * depth without checking for looping files.
39  */
40 #define MAX_CMDFILE_DEPTH 15
42 typedef struct t_cmdfile {
43       char *cmdfile;
44       YY_BUFFER_STATE buffer;
45 } s_cmdfile;
46 s_cmdfile cmdfile_stack[MAX_CMDFILE_DEPTH];
47 int cmdfile_stack_ptr = 0;
51 %x CCOMMENT
52 %x LCOMMENT
53 %x PLUS_ARGS
54 %x FILE_NAME
58   /* Accept C++ style comments. */
59 "//".* { comment_enter = YY_START; BEGIN(LCOMMENT); }
60 <LCOMMENT>.    { yymore(); }
61 <LCOMMENT>\n   { cflloc.first_line += 1; BEGIN(comment_enter); }
63   /* Accept C style comments. */
64 "/*" { comment_enter = YY_START; BEGIN(CCOMMENT); }
65 <CCOMMENT>.    { yymore(); }
66 <CCOMMENT>\n   { cflloc.first_line += 1; yymore(); }
67 <CCOMMENT>"*/" { BEGIN(comment_enter); }
69   /* Accept shell type comments. */
70 ^"#".* { ; }
72   /* Skip white space. */
73 [ \t\f\r] { ; }
74   /* Skip line ends, but also count the line. */
75 \n { cflloc.first_line += 1; }
78 "+define+" { BEGIN(PLUS_ARGS); return TOK_DEFINE; }
80 "+incdir+" { BEGIN(PLUS_ARGS); return TOK_INCDIR; }
82 "+libdir+" { BEGIN(PLUS_ARGS); return TOK_LIBDIR; }
84 "+libdir-nocase+" { BEGIN(PLUS_ARGS); return TOK_LIBDIR_NOCASE; }
86 "+libext+" { BEGIN(PLUS_ARGS); return TOK_LIBEXT; }
88 "+integer-width+" { BEGIN(PLUS_ARGS); return TOK_INTEGER_WIDTH; }
90   /* If it is not any known plus-flag, return the generic form. */
91 "+"[^\n \t\b\f\r+]* {
92       cflval.text = strdup(yytext);
93       BEGIN(PLUS_ARGS);
94       return TOK_PLUSWORD; }
96   /* Once in PLUS_ARGS mode, words are delimited by +
97      characters. White space and line end terminate PLUS_ARGS mode,
98      but + terminates only the word. */
99 <PLUS_ARGS>[^\n \t\b\f\r+]* {
100       cflval.text = strdup(yytext);
101       return TOK_PLUSARG; }
103   /* Within plusargs, this is a delimiter. */
104 <PLUS_ARGS>"+" { }
106   /* White space end plus_args mode. */
107 <PLUS_ARGS>[ \t\b\f\r] { BEGIN(0); }
109 <PLUS_ARGS>\n {
110       cflloc.first_line += 1;
111       BEGIN(0); }
113   /* Notice the -a flag. */
114 "-a" { return TOK_Da; }
116   /* Notice the -c or -f flag. */
117 "-c" { return TOK_Dc; }
118 "-f" { return TOK_Dc; }
120   /* Notice the -v flag. */
121 "-v" { return TOK_Dv; }
123   /* Notice the -y flag. */
124 "-y" { return TOK_Dy; }
126   /* This rule matches paths and strings that may be file names. This
127      is a little bit tricky, as we don't want to mistake a comment for
128      a string word. */
129 "/"[\r\n] { /* Special case of file name "/" */
130       cflval.text = trim_trailing_white(yytext, 0);
131       return TOK_STRING; }
132 "/"[^\*\/] { /* A file name that starts with "/". */
133       yymore();
134       BEGIN(FILE_NAME); }
135 [^/\n \t\b\r+-][^/\n\r]* { /* A file name that starts with other than "/" */
136       yymore();
137       BEGIN(FILE_NAME); }
139 <FILE_NAME>"//" {
140         /* Found a trailing comment. Returning the terminated name. */
141       cflval.text = trim_trailing_white(yytext, 2);
142       BEGIN(LCOMMENT);
143       return TOK_STRING; }
144 <FILE_NAME>"/"?[^/\n\r]* {
145       yymore();
146       /* not a comment... continuing */; }
147 <FILE_NAME>[\n\r] {
148         /* No trailing comment. Return the file name. */
149       cflval.text = trim_trailing_white(yytext, 0);
150       BEGIN(0);
151       return TOK_STRING; }
152        
153   /* Fallback match. */
154 . { return yytext[0]; }
156   /* At the end of file switch back to the previous buffer. */
157 <<EOF>> {
158       if (--cmdfile_stack_ptr < 0) {
159             free(current_file);
160             yyterminate();
161       } else {
162             yy_delete_buffer(YY_CURRENT_BUFFER);
163             yy_switch_to_buffer(cmdfile_stack[cmdfile_stack_ptr].buffer);
164             free(current_file);
165             current_file = cmdfile_stack[cmdfile_stack_ptr].cmdfile;
166       } }
170 static char* trim_trailing_white(char*text, int trim)
172       char*cp = text + strlen(text);
173       while (cp > text && trim > 0) {
174             trim -= 1;
175             cp -= 1;
176             *cp = 0;
177       }
178       while (cp > text && strchr("\n\r\t\b", cp[-1]))
179             cp -= 1;
181       cp[0] = 0;
182       return strdup(text);
185 int yywrap()
187       return 1;
190 void switch_to_command_file(const char *file)
192       char path[4096];
193       char *cp;
195       if (cmdfile_stack_ptr >= MAX_CMDFILE_DEPTH) {
196             fprintf(stderr, "Error: command files nested too deeply (%d) "
197                     "at %s:%d.\n", MAX_CMDFILE_DEPTH, current_file,
198                     cflloc.first_line);
199             exit(1);
200       }
202       cmdfile_stack[cmdfile_stack_ptr].buffer = YY_CURRENT_BUFFER;
203       cmdfile_stack[cmdfile_stack_ptr].cmdfile = current_file;
204       cmdfile_stack_ptr += 1;
206         /*
207          * If this is a relative file then add the current path to the
208          * file name.
209          */
210       if (file[0] != '/') {
211             strcpy(path, current_file);
212             cp = strrchr(path, '/');
213             if (cp == 0) strcpy(path, file);  /* A base file. */
214             else {
215                   *(cp+1) = '\0';
216                   strcat(path, file);
217             }
218       } else strcpy(path, file);  /* An absolute path. */
220       yyin = fopen(path, "r");
221       if (yyin == NULL) {
222             fprintf(stderr, "Error: unable to read nested command file (%s) "
223                     "at %s:%d.\n", path, current_file, cflloc.first_line);
224             exit(1);
225       }
227       current_file = strdup(path);
228       yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
229       cflloc.first_line = 1;
232 void cfreset(FILE*fd, const char*path)
234       yyin = fd;
235       yyrestart(fd);
236       current_file = strdup(path);
237       cflloc.first_line = 1;