]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/engine/scan.c
73188a6920cbdb926f7f8e3c9337345f15cb9140
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 FILE * file
; /* for yyfparse() -- file being read */
38 OBJECT
* fname
; /* for yyfparse() -- file name */
39 int line
; /* line counter for error messages */
40 char buf
[ 512 ]; /* for yyfparse() -- line buffer */
43 static include
* incp
= 0; /* current file; head of chain */
45 static int scanmode
= SCAN_NORMAL
;
46 static int anyerrors
= 0;
49 static char * symdump( YYSTYPE
* );
51 #define BIGGEST_TOKEN 10240 /* no single token can be larger */
55 * Set parser mode: normal, string, or keyword.
64 void yyerror( char const * s
)
66 /* We use yylval instead of incp to access the error location information as
67 * the incp pointer will already be reset to 0 in case the error occurred at
70 * The two may differ only if ran into an unexpected EOF or we get an error
71 * while reading a lexical token spanning multiple lines, e.g. a multi-line
72 * string literal or action body, in which case yylval location information
73 * will hold the information about where the token started while incp will
74 * hold the information about where reading it broke.
76 out_printf( "%s:%d: %s at %s\n", object_str( yylval
.file
), yylval
.line
, s
,
84 return anyerrors
!= 0;
88 void yyfparse( OBJECT
* s
)
90 include
* i
= (include
*)BJAM_MALLOC( sizeof( *i
) );
92 /* Push this onto the incp chain. */
96 i
->fname
= object_copy( s
);
101 /* If the filename is "+", it means use the internal jambase. */
102 if ( !strcmp( object_str( s
), "+" ) )
103 i
->strings
= jambase
;
108 * yyfdone() - cleanup after we're done parsing a file.
112 include
* const i
= incp
;
115 /* Close file, free name. */
116 if(i
->file
&& (i
->file
!= stdin
))
118 object_free(i
->fname
);
119 BJAM_FREE((char *)i
);
124 * yyline() - read new line and return first character.
126 * Fabricates a continuous stream of characters across include files, returning
127 * EOF at the bitter end.
132 include
* const i
= incp
;
137 /* Once we start reading from the input stream, we reset the include
138 * insertion point so that the next include file becomes the head of the
142 /* If there is more data in this line, return it. */
146 /* If we are reading from an internal string list, go to the next string. */
152 i
->string
= *(i
->strings
++);
158 /* If necessary, open the file. */
162 if ( strcmp( object_str( i
->fname
), "-" ) && !( f
= fopen( object_str( i
->fname
), "r" ) ) )
163 perror( object_str( i
->fname
) );
167 /* If there is another line in this file, start it. */
168 if ( i
->file
&& fgets( i
->buf
, sizeof( i
->buf
), i
->file
) )
176 /* This include is done. Return EOF so yyparse() returns to
185 * yylex() - set yylval to current token; return its type.
187 * Macros to move things along:
189 * yychar() - return and advance character; invalid after EOF.
190 * yyprev() - back up one character; invalid before yychar().
192 * yychar() returns a continuous stream of characters, until it hits the EOF of
193 * the current include file.
196 #define yychar() ( *incp->string ? *incp->string++ : yyline() )
197 #define yyprev() ( incp->string-- )
202 char buf
[ BIGGEST_TOKEN
];
208 /* Get first character (whitespace or of token). */
211 if ( scanmode
== SCAN_STRING
)
213 /* If scanning for a string (action's {}'s), look for the closing brace.
214 * We handle matching braces, if they match.
219 while ( ( c
!= EOF
) && ( b
< buf
+ sizeof( buf
) ) )
224 if ( ( c
== '}' ) && !--nest
)
231 /* Turn trailing "\r\n" sequences into plain "\n" for Cygwin. */
232 if ( ( c
== '\n' ) && ( b
[ -1 ] == '\r' ) )
236 /* We ate the ending brace -- regurgitate it. */
240 /* Check for obvious errors. */
241 if ( b
== buf
+ sizeof( buf
) )
243 yyerror( "action block too big" );
249 yyerror( "unmatched {} in action block" );
254 yylval
.type
= STRING
;
255 yylval
.string
= object_new( buf
);
256 yylval
.file
= incp
->fname
;
257 yylval
.line
= incp
->line
;
266 /* Eat white space. */
269 /* Skip past white space. */
270 while ( ( c
!= EOF
) && isspace( c
) )
277 /* Swallow up comment line. */
278 while ( ( ( c
= yychar() ) != EOF
) && ( c
!= '\n' ) ) ;
281 /* c now points to the first character of a token. */
285 yylval
.file
= incp
->fname
;
286 yylval
.line
= incp
->line
;
288 /* While scanning the word, disqualify it for (expensive) keyword lookup
289 * when we can: $anything, "anything", \anything
291 notkeyword
= c
== '$';
293 /* Look for white space to delimit word. "'s get stripped but preserve
294 * white space. \ protects next character.
299 ( b
< buf
+ sizeof( buf
) ) &&
300 ( inquote
|| !isspace( c
) )
309 else if ( c
!= '\\' )
314 else if ( ( c
= yychar() ) != EOF
)
335 /* Check obvious errors. */
336 if ( b
== buf
+ sizeof( buf
) )
338 yyerror( "string too big" );
344 yyerror( "unmatched \" in string" );
348 /* We looked ahead a character - back up. */
352 /* Scan token table. Do not scan if it is obviously not a keyword or if
353 * it is an alphabetic when were looking for punctuation.
359 if ( !notkeyword
&& !( isalpha( *buf
) && ( scanmode
== SCAN_PUNCT
) ) )
360 for ( k
= keywords
; k
->word
; ++k
)
361 if ( ( *buf
== *k
->word
) && !strcmp( k
->word
, buf
) )
363 yylval
.type
= k
->type
;
364 yylval
.keyword
= k
->word
; /* used by symdump */
368 if ( yylval
.type
== ARG
)
369 yylval
.string
= object_new( buf
);
373 out_printf( "scan %s\n", symdump( &yylval
) );
378 /* We do not reset yylval.file & yylval.line here so unexpected EOF error
379 * messages would include correct error location information.
386 static char * symdump( YYSTYPE
* s
)
388 static char buf
[ BIGGEST_TOKEN
+ 20 ];
391 case EOF
: sprintf( buf
, "EOF" ); break;
392 case 0 : sprintf( buf
, "unknown symbol %s", object_str( s
->string
) ); break;
393 case ARG
: sprintf( buf
, "argument %s" , object_str( s
->string
) ); break;
394 case STRING
: sprintf( buf
, "string \"%s\"" , object_str( s
->string
) ); break;
395 default : sprintf( buf
, "keyword %s" , s
->keyword
); break;
402 * Get information about the current file and line, for those epsilon
403 * transitions that produce a parse.
406 void yyinput_last_read_token( OBJECT
* * name
, int * line
)
408 /* TODO: Consider whether and when we might want to report where the last
409 * read token ended, e.g. EOF errors inside string literals.