]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/engine/scan.c
860d98871a718e4b4cb28a107f0c3e9d76390a87
2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
8 * scan.c - the jam yacc scanner
16 #include "constants.h"
27 #include "jamgramtab.h"
31 typedef struct include include
;
34 include
* next
; /* next serial include file */
35 char * string
; /* pointer into current line */
36 char * * strings
; /* for yyfparse() -- text to parse */
37 LISTITER pos
; /* for yysparse() -- text to parse */
38 LIST
* list
; /* for yysparse() -- text to parse */
39 FILE * file
; /* for yyfparse() -- file being read */
40 OBJECT
* fname
; /* for yyfparse() -- file name */
41 int line
; /* line counter for error messages */
42 char buf
[ 512 ]; /* for yyfparse() -- line buffer */
45 static include
* incp
= 0; /* current file; head of chain */
47 static int scanmode
= SCAN_NORMAL
;
48 static int anyerrors
= 0;
51 static char * symdump( YYSTYPE
* );
53 #define BIGGEST_TOKEN 10240 /* no single token can be larger */
57 * Set parser mode: normal, string, or keyword.
66 void yyerror( char const * s
)
68 /* We use yylval instead of incp to access the error location information as
69 * the incp pointer will already be reset to 0 in case the error occurred at
72 * The two may differ only if ran into an unexpected EOF or we get an error
73 * while reading a lexical token spanning multiple lines, e.g. a multi-line
74 * string literal or action body, in which case yylval location information
75 * will hold the information about where the token started while incp will
76 * hold the information about where reading it broke.
78 out_printf( "%s:%d: %s at %s\n", object_str( yylval
.file
), yylval
.line
, s
,
86 return anyerrors
!= 0;
90 void yyfparse( OBJECT
* s
)
92 include
* i
= (include
*)BJAM_MALLOC( sizeof( *i
) );
94 /* Push this onto the incp chain. */
98 i
->fname
= object_copy( s
);
103 /* If the filename is "+", it means use the internal jambase. */
104 if ( !strcmp( object_str( s
), "+" ) )
105 i
->strings
= jambase
;
109 void yysparse( OBJECT
* name
, const char * * lines
)
112 incp
->strings
= (char * *)lines
;
117 * yyfdone() - cleanup after we're done parsing a file.
121 include
* const i
= incp
;
124 /* Close file, free name. */
125 if(i
->file
&& (i
->file
!= stdin
))
127 object_free(i
->fname
);
128 BJAM_FREE((char *)i
);
133 * yyline() - read new line and return first character.
135 * Fabricates a continuous stream of characters across include files, returning
136 * EOF at the bitter end.
141 include
* const i
= incp
;
146 /* Once we start reading from the input stream, we reset the include
147 * insertion point so that the next include file becomes the head of the
151 /* If there is more data in this line, return it. */
155 /* If we are reading from an internal string list, go to the next string. */
161 i
->string
= *(i
->strings
++);
167 /* If necessary, open the file. */
171 if ( strcmp( object_str( i
->fname
), "-" ) && !( f
= fopen( object_str( i
->fname
), "r" ) ) )
172 perror( object_str( i
->fname
) );
176 /* If there is another line in this file, start it. */
177 if ( i
->file
&& fgets( i
->buf
, sizeof( i
->buf
), i
->file
) )
185 /* This include is done. Return EOF so yyparse() returns to
194 * yylex() - set yylval to current token; return its type.
196 * Macros to move things along:
198 * yychar() - return and advance character; invalid after EOF.
199 * yyprev() - back up one character; invalid before yychar().
201 * yychar() returns a continuous stream of characters, until it hits the EOF of
202 * the current include file.
205 #define yychar() ( *incp->string ? *incp->string++ : yyline() )
206 #define yyprev() ( incp->string-- )
211 char buf
[ BIGGEST_TOKEN
];
217 /* Get first character (whitespace or of token). */
220 if ( scanmode
== SCAN_STRING
)
222 /* If scanning for a string (action's {}'s), look for the closing brace.
223 * We handle matching braces, if they match.
228 while ( ( c
!= EOF
) && ( b
< buf
+ sizeof( buf
) ) )
233 if ( ( c
== '}' ) && !--nest
)
240 /* Turn trailing "\r\n" sequences into plain "\n" for Cygwin. */
241 if ( ( c
== '\n' ) && ( b
[ -1 ] == '\r' ) )
245 /* We ate the ending brace -- regurgitate it. */
249 /* Check for obvious errors. */
250 if ( b
== buf
+ sizeof( buf
) )
252 yyerror( "action block too big" );
258 yyerror( "unmatched {} in action block" );
263 yylval
.type
= STRING
;
264 yylval
.string
= object_new( buf
);
265 yylval
.file
= incp
->fname
;
266 yylval
.line
= incp
->line
;
275 /* Eat white space. */
278 /* Skip past white space. */
279 while ( ( c
!= EOF
) && isspace( c
) )
287 if ( ( c
!= EOF
) && c
== '|' )
289 /* Swallow up block comment. */
292 while ( ! ( c0
== '|' && c1
== '#' ) && ( c0
!= EOF
&& c1
!= EOF
) )
301 /* Swallow up comment line. */
302 while ( ( c
!= EOF
) && ( c
!= '\n' ) ) c
= yychar();
306 /* c now points to the first character of a token. */
310 yylval
.file
= incp
->fname
;
311 yylval
.line
= incp
->line
;
313 /* While scanning the word, disqualify it for (expensive) keyword lookup
314 * when we can: $anything, "anything", \anything
316 notkeyword
= c
== '$';
318 /* Look for white space to delimit word. "'s get stripped but preserve
319 * white space. \ protects next character.
324 ( b
< buf
+ sizeof( buf
) ) &&
325 ( inquote
|| !isspace( c
) )
334 else if ( c
!= '\\' )
339 else if ( ( c
= yychar() ) != EOF
)
360 /* Check obvious errors. */
361 if ( b
== buf
+ sizeof( buf
) )
363 yyerror( "string too big" );
369 yyerror( "unmatched \" in string" );
373 /* We looked ahead a character - back up. */
377 /* Scan token table. Do not scan if it is obviously not a keyword or if
378 * it is an alphabetic when were looking for punctuation.
384 if ( !notkeyword
&& !( isalpha( *buf
) && ( scanmode
== SCAN_PUNCT
) ) )
385 for ( k
= keywords
; k
->word
; ++k
)
386 if ( ( *buf
== *k
->word
) && !strcmp( k
->word
, buf
) )
388 yylval
.type
= k
->type
;
389 yylval
.keyword
= k
->word
; /* used by symdump */
393 if ( yylval
.type
== ARG
)
394 yylval
.string
= object_new( buf
);
398 out_printf( "scan %s\n", symdump( &yylval
) );
403 /* We do not reset yylval.file & yylval.line here so unexpected EOF error
404 * messages would include correct error location information.
411 static char * symdump( YYSTYPE
* s
)
413 static char buf
[ BIGGEST_TOKEN
+ 20 ];
416 case EOF
: sprintf( buf
, "EOF" ); break;
417 case 0 : sprintf( buf
, "unknown symbol %s", object_str( s
->string
) ); break;
418 case ARG
: sprintf( buf
, "argument %s" , object_str( s
->string
) ); break;
419 case STRING
: sprintf( buf
, "string \"%s\"" , object_str( s
->string
) ); break;
420 default : sprintf( buf
, "keyword %s" , s
->keyword
); break;
427 * Get information about the current file and line, for those epsilon
428 * transitions that produce a parse.
431 void yyinput_last_read_token( OBJECT
* * name
, int * line
)
433 /* TODO: Consider whether and when we might want to report where the last
434 * read token ended, e.g. EOF errors inside string literals.