1999-07-03 19:24:11 +02:00
|
|
|
|
|
|
|
|
%{
|
|
|
|
|
/*
|
2002-02-15 06:20:58 +01:00
|
|
|
* Copyright (c) 1999-2002 Stephen Williams (steve@icarus.com)
|
1999-07-03 19:24:11 +02: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
|
|
|
|
|
*/
|
2000-08-20 19:49:04 +02:00
|
|
|
#if !defined(WINNT) && !defined(macintosh)
|
2003-07-15 04:41:07 +02:00
|
|
|
#ident "$Id: lexor.lex,v 1.40 2003/07/15 02:41:07 steve Exp $"
|
1999-07-03 19:24:11 +02:00
|
|
|
#endif
|
|
|
|
|
|
2001-07-25 05:10:48 +02:00
|
|
|
# include "config.h"
|
|
|
|
|
|
1999-07-03 19:24:11 +02:00
|
|
|
# include <stdio.h>
|
2001-09-15 20:27:04 +02:00
|
|
|
#ifdef HAVE_MALLOC_H
|
1999-07-03 19:24:11 +02:00
|
|
|
# include <malloc.h>
|
2001-09-15 20:27:04 +02:00
|
|
|
#endif
|
|
|
|
|
# include <stdlib.h>
|
1999-07-03 19:24:11 +02:00
|
|
|
# include <string.h>
|
|
|
|
|
# include <assert.h>
|
|
|
|
|
|
|
|
|
|
# include "parse.h"
|
1999-07-03 22:03:47 +02:00
|
|
|
# include "globals.h"
|
|
|
|
|
|
|
|
|
|
static void output_init();
|
|
|
|
|
#define YY_USER_INIT output_init()
|
1999-07-03 19:24:11 +02:00
|
|
|
|
|
|
|
|
static void def_match();
|
|
|
|
|
static void def_start();
|
2000-03-29 06:36:42 +02:00
|
|
|
static void def_finish();
|
1999-07-11 20:03:56 +02:00
|
|
|
static void def_undefine();
|
1999-07-03 19:24:11 +02:00
|
|
|
static void do_define();
|
2002-03-09 07:37:49 +01:00
|
|
|
static int def_is_done();
|
1999-07-11 18:59:58 +02:00
|
|
|
static int is_defined(const char*name);
|
1999-07-03 19:24:11 +02:00
|
|
|
|
|
|
|
|
static void include_filename();
|
|
|
|
|
static void do_include();
|
|
|
|
|
static int yywrap();
|
|
|
|
|
|
|
|
|
|
|
1999-07-03 22:03:47 +02:00
|
|
|
struct include_stack_t {
|
|
|
|
|
char* path;
|
1999-07-07 03:07:57 +02:00
|
|
|
|
|
|
|
|
/* If the current input is the the file, this member is set. */
|
1999-07-03 22:03:47 +02:00
|
|
|
FILE*file;
|
1999-07-07 03:07:57 +02:00
|
|
|
|
|
|
|
|
/* If we are reparsing a macro expansion, file is 0 and this
|
|
|
|
|
member points to the string is progress */
|
|
|
|
|
const char*str;
|
|
|
|
|
|
1999-07-03 22:03:47 +02:00
|
|
|
unsigned lineno;
|
|
|
|
|
YY_BUFFER_STATE yybs;
|
|
|
|
|
|
|
|
|
|
struct include_stack_t*next;
|
|
|
|
|
};
|
|
|
|
|
|
2002-04-04 07:26:13 +02:00
|
|
|
static void emit_pathline(struct include_stack_t *isp);
|
|
|
|
|
|
1999-09-06 00:33:18 +02:00
|
|
|
static struct include_stack_t*file_queue = 0;
|
1999-07-03 22:03:47 +02:00
|
|
|
static struct include_stack_t*istack = 0;
|
|
|
|
|
static struct include_stack_t*standby = 0;
|
|
|
|
|
|
1999-07-07 03:07:57 +02:00
|
|
|
#define YY_INPUT(buf,result,max_size) do { \
|
|
|
|
|
if (istack->file) { \
|
|
|
|
|
size_t rc = fread(buf, 1, max_size, istack->file); \
|
|
|
|
|
if (rc == 0) result = YY_NULL; \
|
|
|
|
|
else result = rc; \
|
|
|
|
|
} else { \
|
|
|
|
|
if (*istack->str == 0) result = YY_NULL; \
|
|
|
|
|
else { buf[0] = *istack->str++; result = 1; } \
|
|
|
|
|
} \
|
|
|
|
|
} while(0)
|
|
|
|
|
|
1999-07-10 02:36:12 +02:00
|
|
|
static int comment_enter = 0;
|
1999-07-03 19:24:11 +02:00
|
|
|
%}
|
|
|
|
|
|
1999-07-11 18:59:58 +02:00
|
|
|
%option stack
|
|
|
|
|
|
1999-07-03 19:24:11 +02:00
|
|
|
%x PPINCLUDE
|
|
|
|
|
%x PPDEFINE
|
1999-07-10 02:36:12 +02:00
|
|
|
%x CCOMMENT
|
2002-02-15 06:20:58 +01:00
|
|
|
%x PCOMENT
|
1999-07-15 05:39:17 +02:00
|
|
|
%x CSTRING
|
2001-01-20 04:10:35 +01:00
|
|
|
%x ERROR_LINE
|
1999-07-03 19:24:11 +02:00
|
|
|
|
1999-07-11 18:59:58 +02:00
|
|
|
%x IFDEF_FALSE
|
|
|
|
|
%s IFDEF_TRUE
|
|
|
|
|
%x IFDEF_SUPR
|
|
|
|
|
|
|
|
|
|
W [ \t\b\f]+
|
|
|
|
|
|
1999-07-03 19:24:11 +02:00
|
|
|
%%
|
|
|
|
|
|
2003-07-15 04:41:07 +02:00
|
|
|
"//"[^\r\n]* { ECHO; }
|
1999-07-25 02:03:13 +02:00
|
|
|
|
1999-07-10 02:36:12 +02:00
|
|
|
/* detect multiline, c-style comments, passing them directly to the
|
|
|
|
|
output. This is necessary to allow for ignoring directives that
|
|
|
|
|
are included within the comments. */
|
|
|
|
|
|
|
|
|
|
"/*" { comment_enter = YY_START; BEGIN(CCOMMENT); ECHO; }
|
2003-07-15 04:41:07 +02:00
|
|
|
<CCOMMENT>[^\r\n] { ECHO; }
|
|
|
|
|
<CCOMMENT>\n\r { istack->lineno += 1; fputc('\n', yyout); }
|
|
|
|
|
<CCOMMENT>\r\n { istack->lineno += 1; fputc('\n', yyout); }
|
|
|
|
|
<CCOMMENT>\n { istack->lineno += 1; fputc('\n', yyout); }
|
|
|
|
|
<CCOMMENT>\r { istack->lineno += 1; fputc('\n', yyout); }
|
1999-07-10 02:36:12 +02:00
|
|
|
<CCOMMENT>"*/" { BEGIN(comment_enter); ECHO; }
|
|
|
|
|
|
2002-02-15 06:20:58 +01:00
|
|
|
/* Detect and pass multiline pragma comments. As with C-style
|
2003-02-03 01:28:12 +01:00
|
|
|
comments, pragma comments are passed through, and preprocessor
|
|
|
|
|
directives contained within are ignored. Contains macros are
|
|
|
|
|
expanded, however. */
|
2002-02-15 06:20:58 +01:00
|
|
|
|
|
|
|
|
"(*" { comment_enter = YY_START; BEGIN(PCOMENT); ECHO; }
|
2003-07-15 04:41:07 +02:00
|
|
|
<PCOMENT>[^\r\n] { ECHO; }
|
|
|
|
|
<PCOMENT>\n\r { istack->lineno += 1; fputc('\n', yyout); }
|
|
|
|
|
<PCOMENT>\r\n { istack->lineno += 1; fputc('\n', yyout); }
|
|
|
|
|
<PCOMENT>\n { istack->lineno += 1; fputc('\n', yyout); }
|
|
|
|
|
<PCOMENT>\r { istack->lineno += 1; fputc('\n', yyout); }
|
2002-02-15 06:20:58 +01:00
|
|
|
<PCOMENT>"*)" { BEGIN(comment_enter); ECHO; }
|
2003-02-03 01:28:12 +01:00
|
|
|
<PCOMENT>`[a-zA-Z][a-zA-Z0-9_$]* { def_match(); }
|
2002-02-15 06:20:58 +01:00
|
|
|
|
2003-02-03 01:28:12 +01:00
|
|
|
/* Strings do not contain preprocessor directives, but can expand
|
|
|
|
|
macros. If that happens, they get expanded in the context of the
|
|
|
|
|
string. */
|
1999-07-15 05:39:17 +02:00
|
|
|
\" { comment_enter = YY_START; BEGIN(CSTRING); ECHO; }
|
2003-02-03 01:28:12 +01:00
|
|
|
<CSTRING>\\\" { ECHO; }
|
2003-07-15 04:41:07 +02:00
|
|
|
<CSTRING>\r\n { fputc('\n', yyout); }
|
|
|
|
|
<CSTRING>\n\r { fputc('\n', yyout); }
|
|
|
|
|
<CSTRING>\n { fputc('\n', yyout); }
|
|
|
|
|
<CSTRING>\r { fputc('\n', yyout); }
|
1999-07-15 05:39:17 +02:00
|
|
|
<CSTRING>\" { BEGIN(comment_enter); ECHO; }
|
2003-02-03 01:28:12 +01:00
|
|
|
<CSTRING>. { ECHO; }
|
|
|
|
|
<CSTRING>`[a-zA-Z][a-zA-Z0-9_$]* { def_match(); }
|
1999-07-10 02:36:12 +02:00
|
|
|
|
1999-07-03 19:24:11 +02:00
|
|
|
/* This set of patterns matches the include directive and the name
|
|
|
|
|
that follows it. when the directive ends, the do_include function
|
|
|
|
|
performs the include operation. */
|
|
|
|
|
|
2000-04-26 03:35:26 +02:00
|
|
|
^{W}?`include { yy_push_state(PPINCLUDE); }
|
1999-07-03 19:24:11 +02:00
|
|
|
|
2002-04-04 07:26:13 +02:00
|
|
|
<PPINCLUDE>`[a-zA-Z][a-zA-Z0-9_]* { def_match(); }
|
1999-07-03 19:24:11 +02:00
|
|
|
<PPINCLUDE>\"[^\"]*\" { include_filename(); }
|
|
|
|
|
|
1999-07-10 02:36:12 +02:00
|
|
|
<PPINCLUDE>[ \t\b\f] { ; }
|
1999-07-03 19:24:11 +02:00
|
|
|
|
2000-04-26 03:35:26 +02:00
|
|
|
/* Catch single-line comments that share the line with an include
|
|
|
|
|
directive. And while I'm at it, I might as well preserve the
|
|
|
|
|
comment in the output stream. */
|
|
|
|
|
|
|
|
|
|
<PPINCLUDE>"//".* { ECHO; }
|
|
|
|
|
|
|
|
|
|
/* These finish the include directive (EOF or EOL) so I revert the
|
|
|
|
|
lexor state and execute the inclusion. */
|
|
|
|
|
|
2000-08-01 03:38:25 +02:00
|
|
|
<PPINCLUDE>\r\n { istack->lineno += 1; yy_pop_state(); do_include(); }
|
|
|
|
|
<PPINCLUDE>\n\r { istack->lineno += 1; yy_pop_state(); do_include(); }
|
2003-07-15 04:41:07 +02:00
|
|
|
<PPINCLUDE>\n { istack->lineno += 1; yy_pop_state(); do_include(); }
|
|
|
|
|
<PPINCLUDE>\r { istack->lineno += 1; yy_pop_state(); do_include(); }
|
2000-04-26 03:35:26 +02:00
|
|
|
<PPINCLUDE><<EOF>> { istack->lineno += 1; yy_pop_state(); do_include(); }
|
1999-07-03 19:24:11 +02:00
|
|
|
|
2001-01-20 04:10:35 +01:00
|
|
|
/* Anything that is not matched by the above is an error of some
|
|
|
|
|
sort. Print and error message and absorb the rest of the line. */
|
|
|
|
|
<PPINCLUDE>. {
|
2002-04-04 07:26:13 +02:00
|
|
|
emit_pathline(istack);
|
|
|
|
|
fprintf(stderr, "error: malformed `include directive."
|
|
|
|
|
" Did you quote the file name?\n");
|
2001-01-20 04:10:35 +01:00
|
|
|
error_count += 1;
|
|
|
|
|
BEGIN(ERROR_LINE); }
|
1999-07-03 19:24:11 +02:00
|
|
|
|
|
|
|
|
/* Detect the define directive, and match the name. Match any
|
|
|
|
|
white space that might be found, as well. After I get the
|
|
|
|
|
directive and the name, go into PPDEFINE mode and prepare to
|
|
|
|
|
collect the defined value. */
|
|
|
|
|
|
2002-09-11 21:42:37 +02:00
|
|
|
`define{W}[a-zA-Z_][a-zA-Z0-9_$]*{W}? { yy_push_state(PPDEFINE); def_start(); }
|
1999-07-11 18:59:58 +02:00
|
|
|
|
2003-07-15 04:41:07 +02:00
|
|
|
<PPDEFINE>.*[^\r\n] { do_define(); }
|
2000-03-18 07:12:26 +01:00
|
|
|
|
2003-07-15 04:41:07 +02:00
|
|
|
<PPDEFINE>(\n|"\r\n"|"\n\r"|\r) {
|
2002-03-09 07:37:49 +01:00
|
|
|
if (def_is_done()) {
|
|
|
|
|
def_finish();
|
|
|
|
|
istack->lineno += 1;
|
|
|
|
|
yy_pop_state();
|
|
|
|
|
}
|
2000-03-18 07:12:26 +01:00
|
|
|
fputc('\n', yyout);
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-09 07:37:49 +01:00
|
|
|
/* If the define is terminated by an EOF, then finish the define
|
|
|
|
|
whether there was a continuation or not. */
|
2000-03-18 07:12:26 +01:00
|
|
|
<PPDEFINE><<EOF>> {
|
2000-03-29 06:36:42 +02:00
|
|
|
def_finish();
|
1999-07-11 18:59:58 +02:00
|
|
|
istack->lineno += 1;
|
|
|
|
|
fputc('\n', yyout);
|
2000-04-26 03:35:26 +02:00
|
|
|
yy_pop_state();
|
1999-07-11 20:03:56 +02:00
|
|
|
}
|
|
|
|
|
|
2002-09-11 21:42:37 +02:00
|
|
|
`undef{W}[a-zA-Z_][a-zA-Z0-9_$]*{W}?.* { def_undefine(); }
|
1999-07-11 18:59:58 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Detect conditional compilation directives, and parse them. If I
|
|
|
|
|
find the name defined, switch to the IFDEF_TRUE state and stay
|
|
|
|
|
there until I get an `else or `endif. Otherwise, switch to the
|
|
|
|
|
IFDEF_FALSE state and start tossing data.
|
|
|
|
|
|
|
|
|
|
Handle suppressed `ifdef with an additional suppress start
|
|
|
|
|
condition that stacks on top of the IFDEF_FALSE so that output is
|
|
|
|
|
not accidentally turned on within nested ifdefs. */
|
|
|
|
|
|
2002-09-19 22:33:27 +02:00
|
|
|
`ifdef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
1999-07-11 18:59:58 +02:00
|
|
|
char*name = strchr(yytext, '`');
|
|
|
|
|
assert(name);
|
|
|
|
|
name += 6;
|
|
|
|
|
name += strspn(name, " \t\b\f");
|
1999-07-03 19:24:11 +02:00
|
|
|
|
1999-07-11 18:59:58 +02:00
|
|
|
if (is_defined(name)) {
|
|
|
|
|
yy_push_state(IFDEF_TRUE);
|
|
|
|
|
} else {
|
|
|
|
|
yy_push_state(IFDEF_FALSE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-19 22:33:27 +02:00
|
|
|
`ifndef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
2001-10-30 21:48:55 +01:00
|
|
|
char*name = strchr(yytext, '`');
|
|
|
|
|
assert(name);
|
|
|
|
|
name += 7;
|
|
|
|
|
name += strspn(name, " \t\b\f");
|
|
|
|
|
|
|
|
|
|
if (!is_defined(name)) {
|
|
|
|
|
yy_push_state(IFDEF_TRUE);
|
|
|
|
|
} else {
|
|
|
|
|
yy_push_state(IFDEF_FALSE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-25 04:23:08 +02:00
|
|
|
<IFDEF_FALSE,IFDEF_SUPR>`ifdef{W} { yy_push_state(IFDEF_SUPR); }
|
|
|
|
|
<IFDEF_FALSE,IFDEF_SUPR>`ifndef{W} { yy_push_state(IFDEF_SUPR); }
|
1999-07-11 18:59:58 +02:00
|
|
|
|
2002-09-19 22:33:27 +02:00
|
|
|
<IFDEF_TRUE>`else { BEGIN(IFDEF_FALSE); }
|
|
|
|
|
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
|
|
|
|
|
<IFDEF_SUPR>`else { }
|
1999-07-03 19:24:11 +02:00
|
|
|
|
2003-07-15 04:41:07 +02:00
|
|
|
<IFDEF_FALSE,IFDEF_SUPR>"//"[^\r\n]* { }
|
|
|
|
|
<IFDEF_FALSE,IFDEF_SUPR>[^\r\n] { }
|
|
|
|
|
<IFDEF_FALSE,IFDEF_SUPR>\n\r { istack->lineno += 1; fputc('\n', yyout); }
|
|
|
|
|
<IFDEF_FALSE,IFDEF_SUPR>\r\n { istack->lineno += 1; fputc('\n', yyout); }
|
|
|
|
|
<IFDEF_FALSE,IFDEF_SUPR>\n { istack->lineno += 1; fputc('\n', yyout); }
|
|
|
|
|
<IFDEF_FALSE,IFDEF_SUPR>\r { istack->lineno += 1; fputc('\n', yyout); }
|
1999-07-03 19:24:11 +02:00
|
|
|
|
2002-09-19 22:33:27 +02:00
|
|
|
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>`endif {
|
1999-07-11 18:59:58 +02:00
|
|
|
yy_pop_state();
|
|
|
|
|
}
|
1999-07-10 02:36:12 +02:00
|
|
|
|
1999-07-11 18:59:58 +02:00
|
|
|
/* This pattern notices macros and arranges for them to be replaced. */
|
2002-09-11 21:42:37 +02:00
|
|
|
`[a-zA-Z][a-zA-Z0-9_$]* { def_match(); }
|
1999-07-03 19:24:11 +02:00
|
|
|
|
|
|
|
|
/* Any text that is not a directive just gets passed through to the
|
|
|
|
|
output. Very easy. */
|
|
|
|
|
|
2003-07-15 04:41:07 +02:00
|
|
|
[^\r\n] { ECHO; }
|
|
|
|
|
\n\r { istack->lineno += 1; fputc('\n', yyout); }
|
|
|
|
|
\r\n { istack->lineno += 1; fputc('\n', yyout); }
|
|
|
|
|
\n { istack->lineno += 1; fputc('\n', yyout); }
|
|
|
|
|
\r { istack->lineno += 1; fputc('\n', yyout); }
|
1999-07-03 19:24:11 +02:00
|
|
|
|
2001-01-20 04:10:35 +01:00
|
|
|
/* Absorb the rest of the line when a broken directive is detected. */
|
2003-07-15 04:41:07 +02:00
|
|
|
<ERROR_LINE>[^\r\n]* { yy_pop_state(); }
|
2001-01-20 04:10:35 +01:00
|
|
|
|
1999-07-03 19:24:11 +02:00
|
|
|
%%
|
|
|
|
|
/* Defined macros are kept in this table for convenient lookup. As
|
|
|
|
|
`define directives are matched (and the do_define() function
|
|
|
|
|
called) the tree is built up to match names with values. If a
|
|
|
|
|
define redefines an existing name, the new value it taken. */
|
|
|
|
|
struct define_t {
|
|
|
|
|
char*name;
|
|
|
|
|
char*value;
|
2000-09-14 00:33:13 +02:00
|
|
|
/* keywords don't get rescanned for fresh values. */
|
|
|
|
|
int keyword;
|
1999-07-03 19:24:11 +02:00
|
|
|
|
1999-07-11 20:03:56 +02:00
|
|
|
struct define_t*left, *right, *up;
|
1999-07-03 19:24:11 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct define_t*def_table = 0;
|
|
|
|
|
|
1999-07-11 18:59:58 +02:00
|
|
|
static struct define_t*def_lookup(const char*name)
|
1999-07-03 19:24:11 +02:00
|
|
|
{
|
|
|
|
|
struct define_t*cur = def_table;
|
1999-07-11 20:03:56 +02:00
|
|
|
if (cur == 0) return 0;
|
|
|
|
|
assert(cur->up == 0);
|
|
|
|
|
|
1999-07-03 19:24:11 +02:00
|
|
|
while (cur) {
|
1999-07-11 18:59:58 +02:00
|
|
|
int cmp = strcmp(name, cur->name);
|
|
|
|
|
if (cmp == 0) return cur;
|
1999-07-03 19:24:11 +02:00
|
|
|
if (cmp < 0)
|
|
|
|
|
cur = cur->left;
|
|
|
|
|
else
|
|
|
|
|
cur = cur->right;
|
|
|
|
|
}
|
|
|
|
|
|
1999-07-11 18:59:58 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int is_defined(const char*name)
|
|
|
|
|
{
|
|
|
|
|
return def_lookup(name) != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* When a macro use is discovered in the source, this function is
|
|
|
|
|
used to look up the name and emit the substitution in its
|
|
|
|
|
place. If the name is not found, then the `name string is written
|
|
|
|
|
out instead. */
|
|
|
|
|
|
|
|
|
|
static void def_match()
|
|
|
|
|
{
|
|
|
|
|
struct define_t*cur = def_lookup(yytext+1);
|
1999-07-07 03:07:57 +02:00
|
|
|
if (cur) {
|
2000-09-14 00:33:13 +02:00
|
|
|
struct include_stack_t*isp;
|
|
|
|
|
|
|
|
|
|
if (cur->keyword) {
|
|
|
|
|
fprintf(yyout, "%s", cur->value);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isp = calloc(1, sizeof(struct include_stack_t));
|
1999-07-07 03:07:57 +02:00
|
|
|
isp->str = cur->value;
|
|
|
|
|
isp->next = istack;
|
1999-07-10 02:36:12 +02:00
|
|
|
istack->yybs = YY_CURRENT_BUFFER;
|
1999-07-07 03:07:57 +02:00
|
|
|
istack = isp;
|
2003-05-08 18:20:17 +02:00
|
|
|
yy_switch_to_buffer(yy_create_buffer(istack->file, YY_BUF_SIZE));
|
1999-07-07 03:07:57 +02:00
|
|
|
|
|
|
|
|
} else {
|
2002-04-04 07:26:13 +02:00
|
|
|
emit_pathline(istack);
|
|
|
|
|
fprintf(stderr, "warning: macro %s undefined "
|
|
|
|
|
"(and assumed null) at this point.\n", yytext);
|
1999-07-07 03:07:57 +02:00
|
|
|
}
|
1999-07-03 19:24:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char def_name[256];
|
|
|
|
|
|
|
|
|
|
static void def_start()
|
|
|
|
|
{
|
|
|
|
|
sscanf(yytext, "`define %s", def_name);
|
|
|
|
|
}
|
|
|
|
|
|
2000-09-14 00:33:13 +02:00
|
|
|
void define_macro(const char*name, const char*value, int keyword)
|
1999-07-03 19:24:11 +02:00
|
|
|
{
|
|
|
|
|
struct define_t*def = malloc(sizeof(struct define_t));
|
1999-07-03 22:03:47 +02:00
|
|
|
def->name = strdup(name);
|
|
|
|
|
def->value = strdup(value);
|
2000-09-14 00:33:13 +02:00
|
|
|
def->keyword = keyword;
|
1999-07-03 19:24:11 +02:00
|
|
|
def->left = 0;
|
|
|
|
|
def->right = 0;
|
1999-07-11 20:03:56 +02:00
|
|
|
def->up = 0;
|
1999-07-03 19:24:11 +02:00
|
|
|
if (def_table == 0) {
|
|
|
|
|
def_table = def;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
struct define_t*cur = def_table;
|
|
|
|
|
for (;;) {
|
|
|
|
|
int cmp = strcmp(def->name, cur->name);
|
|
|
|
|
if (cmp == 0) {
|
|
|
|
|
free(cur->value);
|
|
|
|
|
cur->value = def->value;
|
|
|
|
|
free(def->name);
|
|
|
|
|
free(def);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
} else if (cmp < 0) {
|
|
|
|
|
if (cur->left == 0) {
|
|
|
|
|
cur->left = def;
|
1999-07-11 20:03:56 +02:00
|
|
|
def->up = cur;
|
1999-07-03 19:24:11 +02:00
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
cur = cur->left;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
if (cur->right == 0) {
|
|
|
|
|
cur->right = def;
|
1999-07-11 20:03:56 +02:00
|
|
|
def->up = cur;
|
1999-07-03 19:24:11 +02:00
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
cur = cur->right;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-09 07:37:49 +01:00
|
|
|
/*
|
|
|
|
|
* The do_define function accumulates the defined value in these
|
|
|
|
|
* variables. When the define is over, the def_finish() function
|
|
|
|
|
* executes the define and clears this text. The define_continue_flag
|
|
|
|
|
* is set if do_define detects that the definition is to be continued
|
|
|
|
|
* on the next line.
|
|
|
|
|
*/
|
|
|
|
|
static char* define_text = 0;
|
|
|
|
|
static size_t define_cnt = 0;
|
|
|
|
|
|
|
|
|
|
static int define_continue_flag = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Collect the definition. Normally, this returns 0. If there is a
|
|
|
|
|
* continuation, then return 1 and this function may be called again
|
|
|
|
|
* to collect another line of the definition.
|
|
|
|
|
*/
|
1999-07-03 22:03:47 +02:00
|
|
|
static void do_define()
|
|
|
|
|
{
|
2002-03-09 07:37:49 +01:00
|
|
|
char *cp;
|
|
|
|
|
|
|
|
|
|
define_continue_flag = 0;
|
|
|
|
|
|
2003-02-03 00:54:35 +01:00
|
|
|
/* Look for comments in the definition, and remove them. The
|
|
|
|
|
"//" style comments go to the end of the line and terminate
|
|
|
|
|
the definition, but the multi-line comments are simply cut
|
|
|
|
|
out, and the define continues. */
|
|
|
|
|
cp = strchr(yytext, '/');
|
|
|
|
|
while (cp && *cp) {
|
|
|
|
|
if (cp[1] == '/') {
|
|
|
|
|
*cp = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cp[1] == '*') {
|
|
|
|
|
char*tail = strstr(cp+2, "*/");
|
|
|
|
|
if (tail == 0) {
|
|
|
|
|
fprintf(stderr, "%s:%u: Unterminated comment "
|
|
|
|
|
"in define\n", istack->path, istack->lineno);
|
|
|
|
|
*cp = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memmove(cp, tail+2, strlen(tail+2)+1);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cp = strchr(cp+1, '/');
|
|
|
|
|
}
|
1999-07-10 02:36:12 +02:00
|
|
|
|
1999-07-17 07:10:13 +02:00
|
|
|
/* Trim trailing white space. */
|
|
|
|
|
cp = yytext + strlen(yytext);
|
|
|
|
|
while (cp > yytext) {
|
2002-03-09 07:37:49 +01:00
|
|
|
if (!isspace(cp[-1]))
|
1999-07-17 07:10:13 +02:00
|
|
|
break;
|
|
|
|
|
|
2002-03-09 07:37:49 +01:00
|
|
|
cp -= 1;
|
1999-07-17 07:10:13 +02:00
|
|
|
*cp = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-09 07:37:49 +01:00
|
|
|
/* Detect the continuation sequence. If I find it, remove it
|
|
|
|
|
and the white space that preceeds it, then replace all that
|
|
|
|
|
with a single newline. */
|
|
|
|
|
if ((cp > yytext) && (cp[-1] == '\\')) {
|
|
|
|
|
|
|
|
|
|
cp -= 1;
|
|
|
|
|
cp[0] = 0;
|
|
|
|
|
while ((cp > yytext) && isspace(cp[-1])) {
|
|
|
|
|
cp -= 1;
|
|
|
|
|
*cp = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*cp++ = '\n';
|
|
|
|
|
*cp = 0;
|
|
|
|
|
define_continue_flag = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Accumulate this text into the define_text string. */
|
|
|
|
|
define_text = realloc(define_text, define_cnt + (cp-yytext) + 1);
|
|
|
|
|
strcpy(define_text+define_cnt, yytext);
|
|
|
|
|
define_cnt += cp-yytext;
|
2000-03-29 06:36:42 +02:00
|
|
|
}
|
|
|
|
|
|
2002-03-09 07:37:49 +01:00
|
|
|
/*
|
|
|
|
|
* Return true if the definition text is done. This is the opposite of
|
|
|
|
|
* the define_continue_flag.
|
|
|
|
|
*/
|
|
|
|
|
static int def_is_done()
|
|
|
|
|
{
|
|
|
|
|
return define_continue_flag? 0 : 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* After some number of calls to do_define, this function is called to
|
|
|
|
|
* assigned value to the parsed name. If there is no value, then
|
|
|
|
|
* assign the string "1"
|
|
|
|
|
*/
|
2000-03-29 06:36:42 +02:00
|
|
|
static void def_finish()
|
|
|
|
|
{
|
2002-03-09 07:37:49 +01:00
|
|
|
define_continue_flag = 0;
|
|
|
|
|
|
|
|
|
|
if (def_name[0]) {
|
|
|
|
|
if (define_text) {
|
|
|
|
|
define_macro(def_name, define_text, 0);
|
|
|
|
|
free(define_text);
|
|
|
|
|
define_text = 0;
|
|
|
|
|
define_cnt = 0;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
define_macro(def_name, "1", 0);
|
|
|
|
|
}
|
|
|
|
|
def_name[0] = 0;
|
|
|
|
|
}
|
1999-07-03 22:03:47 +02:00
|
|
|
}
|
|
|
|
|
|
1999-07-11 20:03:56 +02:00
|
|
|
static void def_undefine()
|
|
|
|
|
{
|
|
|
|
|
struct define_t*cur, *tail;
|
|
|
|
|
|
|
|
|
|
sscanf(yytext, "`undef %s", def_name);
|
|
|
|
|
|
|
|
|
|
cur = def_lookup(def_name);
|
|
|
|
|
if (cur == 0) return;
|
|
|
|
|
|
|
|
|
|
if (cur->up == 0) {
|
|
|
|
|
if ((cur->left == 0) && (cur->right == 0)) {
|
|
|
|
|
def_table = 0;
|
|
|
|
|
|
|
|
|
|
} else if (cur->left == 0) {
|
|
|
|
|
def_table = cur->right;
|
|
|
|
|
if (cur->right)
|
|
|
|
|
cur->right->up = 0;
|
|
|
|
|
|
|
|
|
|
} else if (cur->right == 0) {
|
|
|
|
|
assert(cur->left);
|
|
|
|
|
def_table = cur->left;
|
|
|
|
|
def_table->up = 0;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
tail = cur->left;
|
|
|
|
|
while (tail->right)
|
|
|
|
|
tail = tail->right;
|
|
|
|
|
|
|
|
|
|
tail->right = cur->right;
|
|
|
|
|
tail->right->up = tail;
|
|
|
|
|
|
|
|
|
|
def_table = cur->left;
|
|
|
|
|
def_table->up = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else if (cur->left == 0) {
|
|
|
|
|
|
|
|
|
|
if (cur->up->left == cur) {
|
|
|
|
|
cur->up->left = cur->right;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
assert(cur->up->right == cur);
|
|
|
|
|
cur->up->right = cur->right;
|
|
|
|
|
}
|
|
|
|
|
if (cur->right)
|
|
|
|
|
cur->right->up = cur->up;
|
|
|
|
|
|
|
|
|
|
} else if (cur->right == 0) {
|
|
|
|
|
|
|
|
|
|
assert(cur->left);
|
|
|
|
|
|
|
|
|
|
if (cur->up->left == cur) {
|
|
|
|
|
cur->up->left = cur->left;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
assert(cur->up->right == cur);
|
|
|
|
|
cur->up->right = cur->left;
|
|
|
|
|
}
|
|
|
|
|
cur->left->up = cur->up;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
tail = cur->left;
|
|
|
|
|
assert(cur->left && cur->right);
|
|
|
|
|
while (tail->right)
|
|
|
|
|
tail = tail->right;
|
|
|
|
|
|
|
|
|
|
tail->right = cur->right;
|
|
|
|
|
tail->right->up = tail;
|
|
|
|
|
|
|
|
|
|
if (cur->up->left == cur) {
|
|
|
|
|
cur->up->left = cur->left;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
assert(cur->up->right == cur);
|
|
|
|
|
cur->up->right = cur->left;
|
|
|
|
|
}
|
|
|
|
|
cur->left->up = cur->up;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(cur->name);
|
|
|
|
|
free(cur->value);
|
|
|
|
|
free(cur);
|
|
|
|
|
}
|
|
|
|
|
|
1999-07-03 19:24:11 +02:00
|
|
|
/*
|
|
|
|
|
* Include file handling works by keeping an include stack of the
|
|
|
|
|
* files that are opened and being processed. The first item on the
|
|
|
|
|
* stack is the current file being scanned. If I get to an include
|
|
|
|
|
* statement,
|
|
|
|
|
* open the new file,
|
|
|
|
|
* save the current buffer context,
|
|
|
|
|
* create a new buffer context,
|
|
|
|
|
* and push the new file information.
|
|
|
|
|
*
|
|
|
|
|
* When the file runs out, the yywrap closes the file and deletes the
|
|
|
|
|
* buffer. If after popping the current file information there is
|
|
|
|
|
* another file on the stack, restore its buffer context and resume
|
|
|
|
|
* parsing.
|
|
|
|
|
*/
|
|
|
|
|
|
1999-07-03 22:03:47 +02:00
|
|
|
static void output_init()
|
|
|
|
|
{
|
|
|
|
|
if (line_direct_flag)
|
2001-10-30 22:53:27 +01:00
|
|
|
fprintf(yyout, "`line 1 \"%s\" 0\n", istack->path);
|
1999-07-03 22:03:47 +02:00
|
|
|
}
|
1999-07-03 19:24:11 +02:00
|
|
|
|
|
|
|
|
static void include_filename()
|
|
|
|
|
{
|
2002-04-04 07:26:13 +02:00
|
|
|
if(standby) {
|
|
|
|
|
emit_pathline(istack);
|
|
|
|
|
fprintf(stderr, "error: malformed `include directive. Extra junk on line?\n");
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
1999-07-03 19:24:11 +02:00
|
|
|
standby = malloc(sizeof(struct include_stack_t));
|
|
|
|
|
standby->path = strdup(yytext+1);
|
|
|
|
|
standby->path[strlen(standby->path)-1] = 0;
|
1999-07-03 22:03:47 +02:00
|
|
|
standby->lineno = 0;
|
1999-07-03 19:24:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void do_include()
|
|
|
|
|
{
|
1999-07-03 22:03:47 +02:00
|
|
|
|
|
|
|
|
if (standby->path[0] == '/') {
|
|
|
|
|
standby->file = fopen(standby->path, "r");
|
2002-04-04 07:26:13 +02:00
|
|
|
if(depend_file && standby->file) {
|
|
|
|
|
fprintf(depend_file, "%s\n", istack->path);
|
|
|
|
|
}
|
1999-07-03 22:03:47 +02:00
|
|
|
} else {
|
|
|
|
|
unsigned idx = 0;
|
|
|
|
|
standby->file = 0;
|
|
|
|
|
for (idx = 0 ; idx < include_cnt ; idx += 1) {
|
|
|
|
|
char path[4096];
|
|
|
|
|
sprintf(path, "%s/%s", include_dir[idx], standby->path);
|
|
|
|
|
standby->file = fopen(path, "r");
|
2002-04-04 07:26:13 +02:00
|
|
|
if (standby->file) {
|
|
|
|
|
if(depend_file) {
|
|
|
|
|
fprintf(depend_file, "%s\n", path);
|
|
|
|
|
}
|
1999-07-03 22:03:47 +02:00
|
|
|
break;
|
2002-04-04 07:26:13 +02:00
|
|
|
}
|
1999-07-03 22:03:47 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1999-07-03 19:24:11 +02:00
|
|
|
if (standby->file == 0) {
|
2002-01-06 05:51:31 +01:00
|
|
|
fprintf(stderr, "%s:%u: Include file %s not found\n",
|
|
|
|
|
istack->path, istack->lineno, standby->path);
|
1999-07-03 19:24:11 +02:00
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(standby->file);
|
|
|
|
|
standby->next = istack;
|
|
|
|
|
istack->yybs = YY_CURRENT_BUFFER;
|
|
|
|
|
istack = standby;
|
|
|
|
|
standby = 0;
|
2003-05-08 18:20:17 +02:00
|
|
|
yy_switch_to_buffer(yy_create_buffer(istack->file, YY_BUF_SIZE));
|
1999-07-03 22:03:47 +02:00
|
|
|
|
1999-07-07 03:07:57 +02:00
|
|
|
if (line_direct_flag && istack->path)
|
2001-10-30 22:53:27 +01:00
|
|
|
fprintf(yyout, "\n`line %u \"%s\" 1\n",
|
|
|
|
|
istack->lineno+1, istack->path);
|
1999-07-03 19:24:11 +02:00
|
|
|
}
|
|
|
|
|
|
2002-04-04 07:26:13 +02:00
|
|
|
/* walk the include stack until we find an entry with a valid pathname,
|
|
|
|
|
* and print the file and line from that entry for use in an error message.
|
|
|
|
|
* The istack entries created by def_match() for macro expansions do not
|
|
|
|
|
* contain pathnames. This finds instead the real file in which the outermost
|
|
|
|
|
* macro was used.
|
|
|
|
|
*/
|
|
|
|
|
static void emit_pathline(struct include_stack_t*isp)
|
|
|
|
|
{
|
|
|
|
|
while(isp && (isp->path == NULL)) {
|
|
|
|
|
isp = isp->next;
|
|
|
|
|
}
|
|
|
|
|
assert(isp);
|
|
|
|
|
fprintf(stderr, "%s:%u: ",
|
|
|
|
|
isp->path, isp->lineno+1);
|
|
|
|
|
}
|
|
|
|
|
|
1999-09-06 00:33:18 +02:00
|
|
|
/*
|
|
|
|
|
* The lexical analyzer calls this function when the current file
|
|
|
|
|
* ends. Here I pop the include stack and resume the previous file. If
|
|
|
|
|
* there is no previous file, then the main input is ended.
|
|
|
|
|
*/
|
1999-07-03 19:24:11 +02:00
|
|
|
static int yywrap()
|
|
|
|
|
{
|
1999-07-16 00:53:47 +02:00
|
|
|
int line_mask_flag = 0;
|
1999-07-03 19:24:11 +02:00
|
|
|
struct include_stack_t*isp = istack;
|
|
|
|
|
istack = isp->next;
|
|
|
|
|
|
1999-09-06 00:33:18 +02:00
|
|
|
/* Delete the current input buffers, and free the cell. */
|
1999-07-03 19:24:11 +02:00
|
|
|
yy_delete_buffer(YY_CURRENT_BUFFER);
|
1999-07-07 03:07:57 +02:00
|
|
|
if (isp->file) {
|
|
|
|
|
fclose(isp->file);
|
|
|
|
|
free(isp->path);
|
|
|
|
|
} else {
|
|
|
|
|
/* If I am printing line directives and I just finished
|
|
|
|
|
macro substitution, I should terminate the line and
|
|
|
|
|
arrange for a new directive to be printed. */
|
1999-07-16 00:53:47 +02:00
|
|
|
if (line_direct_flag
|
|
|
|
|
&& istack && istack->path
|
|
|
|
|
&& strchr(isp->str, '\n'))
|
1999-07-07 03:07:57 +02:00
|
|
|
fprintf(yyout, "\n");
|
1999-07-16 00:53:47 +02:00
|
|
|
else
|
|
|
|
|
line_mask_flag = 1;
|
1999-07-07 03:07:57 +02:00
|
|
|
}
|
1999-07-03 19:24:11 +02:00
|
|
|
free(isp);
|
|
|
|
|
|
1999-09-06 00:33:18 +02:00
|
|
|
/* If I am out if include stack, the main input is
|
|
|
|
|
done. Look for another file to process in the input
|
|
|
|
|
queue. If none are there, give up. Otherwise, open the file
|
|
|
|
|
and continue parsing. */
|
|
|
|
|
if (istack == 0) {
|
|
|
|
|
if (file_queue == 0)
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
istack = file_queue;
|
|
|
|
|
file_queue = file_queue->next;
|
|
|
|
|
istack->next = 0;
|
|
|
|
|
istack->lineno = 0;
|
|
|
|
|
|
|
|
|
|
istack->file = fopen(istack->path, "r");
|
|
|
|
|
if (istack->file == 0) {
|
|
|
|
|
perror(istack->path);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (line_direct_flag)
|
2001-10-30 22:53:27 +01:00
|
|
|
fprintf(yyout, "\n`line 1 \"%s\" 0\n", istack->path);
|
2002-04-04 07:26:13 +02:00
|
|
|
if(depend_file) {
|
|
|
|
|
fprintf(depend_file, "%s\n", istack->path);
|
|
|
|
|
}
|
1999-09-06 00:33:18 +02:00
|
|
|
|
2000-03-05 07:13:29 +01:00
|
|
|
yyrestart(istack->file);
|
1999-09-06 00:33:18 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Otherwise, resume the input buffer that is the new stack
|
|
|
|
|
top. If I need to print a line directive, do so. */
|
1999-07-03 19:24:11 +02:00
|
|
|
|
|
|
|
|
yy_switch_to_buffer(istack->yybs);
|
1999-07-03 22:03:47 +02:00
|
|
|
|
1999-07-16 00:53:47 +02:00
|
|
|
if (line_direct_flag && istack->path && !line_mask_flag)
|
2001-10-30 22:53:27 +01:00
|
|
|
fprintf(yyout, "\n`line %u \"%s\" 2\n",
|
|
|
|
|
istack->lineno+1, istack->path);
|
1999-09-06 00:33:18 +02:00
|
|
|
|
1999-07-03 19:24:11 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This function initializes the whole process. The first file is
|
|
|
|
|
* opened, and the lexor is initialized. The include stack is cleared
|
|
|
|
|
* and ready to go.
|
|
|
|
|
*/
|
1999-09-06 00:33:18 +02:00
|
|
|
void reset_lexor(FILE*out, char*paths[])
|
1999-07-03 19:24:11 +02:00
|
|
|
{
|
1999-09-06 00:33:18 +02:00
|
|
|
unsigned idx;
|
|
|
|
|
struct include_stack_t*tail = 0;
|
1999-07-03 19:24:11 +02:00
|
|
|
struct include_stack_t*isp = malloc(sizeof(struct include_stack_t));
|
1999-09-06 00:33:18 +02:00
|
|
|
isp->path = strdup(paths[0]);
|
|
|
|
|
isp->file = fopen(paths[0], "r");
|
1999-07-07 03:07:57 +02:00
|
|
|
isp->str = 0;
|
1999-07-03 19:24:11 +02:00
|
|
|
if (isp->file == 0) {
|
1999-09-06 00:33:18 +02:00
|
|
|
perror(paths[0]);
|
1999-07-03 19:24:11 +02:00
|
|
|
exit(1);
|
|
|
|
|
}
|
2002-04-04 07:26:13 +02:00
|
|
|
if(depend_file) {
|
|
|
|
|
fprintf(depend_file, "%s\n", paths[0]);
|
|
|
|
|
}
|
1999-07-03 19:24:11 +02:00
|
|
|
|
1999-07-03 22:03:47 +02:00
|
|
|
yyout = out;
|
|
|
|
|
|
1999-07-03 19:24:11 +02:00
|
|
|
yyrestart(isp->file);
|
|
|
|
|
|
|
|
|
|
assert(istack == 0);
|
|
|
|
|
istack = isp;
|
|
|
|
|
isp->next = 0;
|
1999-09-06 00:33:18 +02:00
|
|
|
|
|
|
|
|
/* Now build up a queue of all the remaining file names, so
|
|
|
|
|
that yywrap can pull them when needed. */
|
|
|
|
|
file_queue = 0;
|
|
|
|
|
for (idx = 1 ; paths[idx] ; idx += 1) {
|
|
|
|
|
isp = malloc(sizeof(struct include_stack_t));
|
|
|
|
|
isp->path = strdup(paths[idx]);
|
|
|
|
|
isp->str = 0;
|
|
|
|
|
isp->next = 0;
|
|
|
|
|
if (tail)
|
|
|
|
|
tail->next = isp;
|
|
|
|
|
else
|
|
|
|
|
file_queue = isp;
|
|
|
|
|
|
|
|
|
|
tail = isp;
|
|
|
|
|
}
|
1999-07-03 19:24:11 +02:00
|
|
|
}
|