7 * Copyright (c) 2001 Stephen Williams (steve@icarus.com)
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)
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.
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
25 #ident "$Id: cflexor.lex,v 1.11 2007/03/22 16:08:18 steve Exp $"
29 # include "cfparse_misc.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.
40 #define MAX_CMDFILE_DEPTH 15
42 typedef struct t_cmdfile {
44 YY_BUFFER_STATE buffer;
46 s_cmdfile cmdfile_stack[MAX_CMDFILE_DEPTH];
47 int cmdfile_stack_ptr = 0;
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. */
72 /* Skip white space. */
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. */
92 cflval.text = strdup(yytext);
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. */
106 /* White space end plus_args mode. */
107 <PLUS_ARGS>[ \t\b\f\r] { BEGIN(0); }
110 cflloc.first_line += 1;
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
129 "/"[\r\n] { /* Special case of file name "/" */
130 cflval.text = trim_trailing_white(yytext, 0);
132 "/"[^\*\/] { /* A file name that starts with "/". */
135 [^/\n \t\b\r+-][^/\n\r]* { /* A file name that starts with other than "/" */
140 /* Found a trailing comment. Returning the terminated name. */
141 cflval.text = trim_trailing_white(yytext, 2);
144 <FILE_NAME>"/"?[^/\n\r]* {
146 /* not a comment... continuing */; }
148 /* No trailing comment. Return the file name. */
149 cflval.text = trim_trailing_white(yytext, 0);
153 /* Fallback match. */
154 . { return yytext[0]; }
156 /* At the end of file switch back to the previous buffer. */
158 if (--cmdfile_stack_ptr < 0) {
162 yy_delete_buffer(YY_CURRENT_BUFFER);
163 yy_switch_to_buffer(cmdfile_stack[cmdfile_stack_ptr].buffer);
165 current_file = cmdfile_stack[cmdfile_stack_ptr].cmdfile;
170 static char* trim_trailing_white(char*text, int trim)
172 char*cp = text + strlen(text);
173 while (cp > text && trim > 0) {
178 while (cp > text && strchr("\n\r\t\b", cp[-1]))
190 void switch_to_command_file(const char *file)
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,
202 cmdfile_stack[cmdfile_stack_ptr].buffer = YY_CURRENT_BUFFER;
203 cmdfile_stack[cmdfile_stack_ptr].cmdfile = current_file;
204 cmdfile_stack_ptr += 1;
207 * If this is a relative file then add the current path to the
210 if (file[0] != '/') {
211 strcpy(path, current_file);
212 cp = strrchr(path, '/');
213 if (cp == 0) strcpy(path, file); /* A base file. */
218 } else strcpy(path, file); /* An absolute path. */
220 yyin = fopen(path, "r");
222 fprintf(stderr, "Error: unable to read nested command file (%s) "
223 "at %s:%d.\n", path, current_file, cflloc.first_line);
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)
236 current_file = strdup(path);
237 cflloc.first_line = 1;