2011-04-28 02:08:42 +02:00
|
|
|
%option prefix="cf"
|
2008-01-04 20:33:03 +01:00
|
|
|
%option nounput
|
2008-01-05 04:21:26 +01:00
|
|
|
%option noinput
|
2008-01-04 20:33:03 +01:00
|
|
|
|
2001-11-12 02:26:36 +01:00
|
|
|
%{
|
|
|
|
|
/*
|
2009-05-20 04:09:32 +02:00
|
|
|
* Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com)
|
2001-11-12 02:26:36 +01:00
|
|
|
*
|
|
|
|
|
* This source code is free software; you can redistribute it
|
|
|
|
|
* and/or modify it in source code form under the terms of the GNU
|
|
|
|
|
* General Public License as published by the Free Software
|
|
|
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
|
|
|
* any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program 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 this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
# include "cfparse.h"
|
|
|
|
|
# include "cfparse_misc.h"
|
2001-11-12 19:47:32 +01:00
|
|
|
# include "globals.h"
|
2001-11-12 02:26:36 +01:00
|
|
|
# include <string.h>
|
|
|
|
|
|
2007-09-30 02:48:36 +02:00
|
|
|
static int comment_enter;
|
|
|
|
|
static char* trim_trailing_white(char*txt, int trim);
|
|
|
|
|
|
2001-11-12 02:26:36 +01:00
|
|
|
/*
|
2007-09-30 02:48:36 +02:00
|
|
|
* Mostly copied from the flex manual. Do not make this arbitrary
|
|
|
|
|
* depth without checking for looping files.
|
2001-11-12 02:26:36 +01:00
|
|
|
*/
|
2007-09-30 02:48:36 +02:00
|
|
|
#define MAX_CMDFILE_DEPTH 15
|
2001-11-12 02:26:36 +01:00
|
|
|
|
2007-09-30 02:48:36 +02:00
|
|
|
typedef struct t_cmdfile {
|
|
|
|
|
char *cmdfile;
|
|
|
|
|
YY_BUFFER_STATE buffer;
|
|
|
|
|
} s_cmdfile;
|
|
|
|
|
s_cmdfile cmdfile_stack[MAX_CMDFILE_DEPTH];
|
|
|
|
|
int cmdfile_stack_ptr = 0;
|
2001-11-12 02:26:36 +01:00
|
|
|
|
|
|
|
|
%}
|
|
|
|
|
|
|
|
|
|
%x CCOMMENT
|
|
|
|
|
%x LCOMMENT
|
2001-11-13 04:30:26 +01:00
|
|
|
%x PLUS_ARGS
|
2006-11-30 07:00:28 +01:00
|
|
|
%x FILE_NAME
|
2001-11-12 02:26:36 +01:00
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
|
|
/* Accept C++ style comments. */
|
|
|
|
|
"//".* { comment_enter = YY_START; BEGIN(LCOMMENT); }
|
|
|
|
|
<LCOMMENT>. { yymore(); }
|
2007-09-30 02:48:36 +02:00
|
|
|
<LCOMMENT>\n { cflloc.first_line += 1; BEGIN(comment_enter); }
|
2001-11-12 02:26:36 +01:00
|
|
|
|
|
|
|
|
/* Accept C style comments. */
|
|
|
|
|
"/*" { comment_enter = YY_START; BEGIN(CCOMMENT); }
|
|
|
|
|
<CCOMMENT>. { yymore(); }
|
2007-09-30 02:48:36 +02:00
|
|
|
<CCOMMENT>\n { cflloc.first_line += 1; yymore(); }
|
2001-11-12 02:26:36 +01:00
|
|
|
<CCOMMENT>"*/" { BEGIN(comment_enter); }
|
|
|
|
|
|
|
|
|
|
/* Accept shell type comments. */
|
|
|
|
|
^"#".* { ; }
|
|
|
|
|
|
|
|
|
|
/* Skip white space. */
|
2001-12-08 05:13:07 +01:00
|
|
|
[ \t\f\r] { ; }
|
2001-11-12 02:26:36 +01:00
|
|
|
/* Skip line ends, but also count the line. */
|
2007-09-30 02:48:36 +02:00
|
|
|
\n { cflloc.first_line += 1; }
|
2001-11-12 02:26:36 +01:00
|
|
|
|
2001-11-13 04:30:26 +01:00
|
|
|
|
|
|
|
|
"+define+" { BEGIN(PLUS_ARGS); return TOK_DEFINE; }
|
|
|
|
|
|
|
|
|
|
"+incdir+" { BEGIN(PLUS_ARGS); return TOK_INCDIR; }
|
2001-11-12 19:47:32 +01:00
|
|
|
|
2009-12-30 05:23:58 +01:00
|
|
|
"+integer-width+" { BEGIN(PLUS_ARGS); return TOK_INTEGER_WIDTH; }
|
|
|
|
|
|
2002-05-28 22:40:37 +02:00
|
|
|
"+libdir+" { BEGIN(PLUS_ARGS); return TOK_LIBDIR; }
|
|
|
|
|
|
|
|
|
|
"+libdir-nocase+" { BEGIN(PLUS_ARGS); return TOK_LIBDIR_NOCASE; }
|
|
|
|
|
|
2001-11-16 06:07:19 +01:00
|
|
|
"+libext+" { BEGIN(PLUS_ARGS); return TOK_LIBEXT; }
|
|
|
|
|
|
2009-12-30 05:23:58 +01:00
|
|
|
"+parameter+" { BEGIN(PLUS_ARGS); return TOK_PARAMETER; }
|
|
|
|
|
|
|
|
|
|
"+timescale+" { BEGIN(PLUS_ARGS); return TOK_TIMESCALE; }
|
2001-11-16 06:07:19 +01:00
|
|
|
|
2011-07-25 00:24:32 +02:00
|
|
|
"+vhdl-work+" { BEGIN(PLUS_ARGS); return TOK_VHDL_WORK; }
|
|
|
|
|
|
2001-11-12 19:47:32 +01:00
|
|
|
/* If it is not any known plus-flag, return the generic form. */
|
2001-11-13 04:30:26 +01:00
|
|
|
"+"[^\n \t\b\f\r+]* {
|
|
|
|
|
cflval.text = strdup(yytext);
|
|
|
|
|
BEGIN(PLUS_ARGS);
|
|
|
|
|
return TOK_PLUSWORD; }
|
|
|
|
|
|
|
|
|
|
/* Once in PLUS_ARGS mode, words are delimited by +
|
|
|
|
|
characters. White space and line end terminate PLUS_ARGS mode,
|
|
|
|
|
but + terminates only the word. */
|
|
|
|
|
<PLUS_ARGS>[^\n \t\b\f\r+]* {
|
|
|
|
|
cflval.text = strdup(yytext);
|
|
|
|
|
return TOK_PLUSARG; }
|
|
|
|
|
|
|
|
|
|
/* Within plusargs, this is a delimiter. */
|
|
|
|
|
<PLUS_ARGS>"+" { }
|
|
|
|
|
|
|
|
|
|
/* White space end plus_args mode. */
|
|
|
|
|
<PLUS_ARGS>[ \t\b\f\r] { BEGIN(0); }
|
|
|
|
|
|
|
|
|
|
<PLUS_ARGS>\n {
|
2007-09-30 02:48:36 +02:00
|
|
|
cflloc.first_line += 1;
|
2001-11-13 04:30:26 +01:00
|
|
|
BEGIN(0); }
|
2001-11-12 19:47:32 +01:00
|
|
|
|
|
|
|
|
/* Notice the -a flag. */
|
|
|
|
|
"-a" { return TOK_Da; }
|
|
|
|
|
|
2007-09-30 02:48:36 +02:00
|
|
|
/* Notice the -c or -f flag. */
|
|
|
|
|
"-c" { return TOK_Dc; }
|
|
|
|
|
"-f" { return TOK_Dc; }
|
|
|
|
|
|
2001-11-12 19:47:32 +01:00
|
|
|
/* Notice the -v flag. */
|
|
|
|
|
"-v" { return TOK_Dv; }
|
|
|
|
|
|
|
|
|
|
/* Notice the -y flag. */
|
2001-11-12 02:26:36 +01:00
|
|
|
"-y" { return TOK_Dy; }
|
|
|
|
|
|
2001-11-13 04:30:26 +01:00
|
|
|
/* This rule matches paths and strings that may be file names. This
|
|
|
|
|
is a little bit tricky, as we don't want to mistake a comment for
|
|
|
|
|
a string word. */
|
2006-11-30 07:00:28 +01:00
|
|
|
"/"[\r\n] { /* Special case of file name "/" */
|
|
|
|
|
cflval.text = trim_trailing_white(yytext, 0);
|
|
|
|
|
return TOK_STRING; }
|
|
|
|
|
"/"[^\*\/] { /* A file name that starts with "/". */
|
|
|
|
|
yymore();
|
|
|
|
|
BEGIN(FILE_NAME); }
|
2007-03-22 17:08:14 +01:00
|
|
|
[^/\n \t\b\r+-][^/\n\r]* { /* A file name that starts with other than "/" */
|
2006-11-30 07:00:28 +01:00
|
|
|
yymore();
|
|
|
|
|
BEGIN(FILE_NAME); }
|
|
|
|
|
|
|
|
|
|
<FILE_NAME>"//" {
|
|
|
|
|
/* Found a trailing comment. Returning the terminated name. */
|
|
|
|
|
cflval.text = trim_trailing_white(yytext, 2);
|
|
|
|
|
BEGIN(LCOMMENT);
|
|
|
|
|
return TOK_STRING; }
|
|
|
|
|
<FILE_NAME>"/"?[^/\n\r]* {
|
|
|
|
|
yymore();
|
|
|
|
|
/* not a comment... continuing */; }
|
|
|
|
|
<FILE_NAME>[\n\r] {
|
|
|
|
|
/* No trailing comment. Return the file name. */
|
|
|
|
|
cflval.text = trim_trailing_white(yytext, 0);
|
|
|
|
|
BEGIN(0);
|
|
|
|
|
return TOK_STRING; }
|
2008-09-04 18:41:51 +02:00
|
|
|
|
2001-11-12 02:26:36 +01:00
|
|
|
/* Fallback match. */
|
|
|
|
|
. { return yytext[0]; }
|
|
|
|
|
|
2007-09-30 02:48:36 +02:00
|
|
|
/* At the end of file switch back to the previous buffer. */
|
|
|
|
|
<<EOF>> {
|
|
|
|
|
if (--cmdfile_stack_ptr < 0) {
|
|
|
|
|
free(current_file);
|
|
|
|
|
yyterminate();
|
|
|
|
|
} else {
|
|
|
|
|
yy_delete_buffer(YY_CURRENT_BUFFER);
|
|
|
|
|
yy_switch_to_buffer(cmdfile_stack[cmdfile_stack_ptr].buffer);
|
|
|
|
|
free(current_file);
|
|
|
|
|
current_file = cmdfile_stack[cmdfile_stack_ptr].cmdfile;
|
|
|
|
|
} }
|
|
|
|
|
|
2001-11-12 02:26:36 +01:00
|
|
|
%%
|
|
|
|
|
|
2006-11-30 07:00:28 +01:00
|
|
|
static char* trim_trailing_white(char*text, int trim)
|
|
|
|
|
{
|
|
|
|
|
char*cp = text + strlen(text);
|
|
|
|
|
while (cp > text && trim > 0) {
|
|
|
|
|
trim -= 1;
|
|
|
|
|
cp -= 1;
|
|
|
|
|
*cp = 0;
|
|
|
|
|
}
|
|
|
|
|
while (cp > text && strchr("\n\r\t\b", cp[-1]))
|
|
|
|
|
cp -= 1;
|
|
|
|
|
|
|
|
|
|
cp[0] = 0;
|
|
|
|
|
return strdup(text);
|
|
|
|
|
}
|
|
|
|
|
|
2001-11-12 02:26:36 +01:00
|
|
|
int yywrap()
|
|
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2007-09-30 02:48:36 +02:00
|
|
|
void switch_to_command_file(const char *file)
|
|
|
|
|
{
|
|
|
|
|
char path[4096];
|
|
|
|
|
char *cp;
|
|
|
|
|
|
|
|
|
|
if (cmdfile_stack_ptr >= MAX_CMDFILE_DEPTH) {
|
|
|
|
|
fprintf(stderr, "Error: command files nested too deeply (%d) "
|
|
|
|
|
"at %s:%d.\n", MAX_CMDFILE_DEPTH, current_file,
|
|
|
|
|
cflloc.first_line);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmdfile_stack[cmdfile_stack_ptr].buffer = YY_CURRENT_BUFFER;
|
|
|
|
|
cmdfile_stack[cmdfile_stack_ptr].cmdfile = current_file;
|
|
|
|
|
cmdfile_stack_ptr += 1;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If this is a relative file then add the current path to the
|
|
|
|
|
* file name.
|
|
|
|
|
*/
|
|
|
|
|
if (file[0] != '/') {
|
|
|
|
|
strcpy(path, current_file);
|
|
|
|
|
cp = strrchr(path, '/');
|
|
|
|
|
if (cp == 0) strcpy(path, file); /* A base file. */
|
|
|
|
|
else {
|
|
|
|
|
*(cp+1) = '\0';
|
|
|
|
|
strcat(path, file);
|
|
|
|
|
}
|
|
|
|
|
} else strcpy(path, file); /* An absolute path. */
|
|
|
|
|
|
|
|
|
|
yyin = fopen(path, "r");
|
|
|
|
|
if (yyin == NULL) {
|
|
|
|
|
fprintf(stderr, "Error: unable to read nested command file (%s) "
|
|
|
|
|
"at %s:%d.\n", path, current_file, cflloc.first_line);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
current_file = strdup(path);
|
|
|
|
|
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
|
|
|
|
|
cflloc.first_line = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2001-11-12 19:47:32 +01:00
|
|
|
void cfreset(FILE*fd, const char*path)
|
2001-11-12 02:26:36 +01:00
|
|
|
{
|
|
|
|
|
yyin = fd;
|
|
|
|
|
yyrestart(fd);
|
2007-09-30 02:48:36 +02:00
|
|
|
current_file = strdup(path);
|
|
|
|
|
cflloc.first_line = 1;
|
2001-11-12 02:26:36 +01:00
|
|
|
}
|
2009-05-20 04:09:32 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Modern version of flex (>=2.5.9) can clean up the scanner data.
|
|
|
|
|
*/
|
|
|
|
|
void destroy_lexor()
|
|
|
|
|
{
|
|
|
|
|
# ifdef FLEX_SCANNER
|
|
|
|
|
# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5
|
|
|
|
|
# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9
|
|
|
|
|
yylex_destroy();
|
|
|
|
|
# endif
|
|
|
|
|
# endif
|
|
|
|
|
# endif
|
|
|
|
|
}
|