pgc.l 32.4 KB
Newer Older
1
%{
2 3 4 5 6 7 8 9
/*-------------------------------------------------------------------------
 *
 * pgc.l
 *	  lexical scanner for ecpg
 *
 * This is a modified version of src/backend/parser/scan.l
 *
 *
10
 * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
B
Add:  
Bruce Momjian 已提交
11
 * Portions Copyright (c) 1994, Regents of the University of California
12 13 14
 *
 *
 * IDENTIFICATION
15
 *	  $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.144 2006/03/05 15:59:08 momjian Exp $
16 17 18
 *
 *-------------------------------------------------------------------------
 */
19 20
#include "postgres_fe.h"

M
Marc G. Fournier 已提交
21
#include <ctype.h>
M
Marc G. Fournier 已提交
22
#include <sys/types.h>
23
#include <limits.h>
24
#include <errno.h>
25

M
 
Marc G. Fournier 已提交
26
#include "extern.h"
27

M
Marc G. Fournier 已提交
28
extern YYSTYPE yylval;
29

30
static int		xcdepth = 0;	/* depth of nesting in slash-star comments */
31 32 33
static char	   *dolqstart;      /* current $foo$ quote start string */
bool			escape_string_warning;
static bool		warn_on_first_escape;
34

35 36 37 38 39 40
/*
 * literalbuf is used to accumulate literal values when multiple rules
 * are needed to parse a single literal.  Call startlit to reset buffer
 * to empty, addlit to add text.  Note that the buffer is permanently
 * malloc'd to the largest size needed so far in the current run.
 */
41 42 43
static char    *literalbuf = NULL;		/* expandable buffer */
static int		literallen;				/* actual current length */
static int		literalalloc;			/* current allocated buffer size */
44

45
#define startlit()	(literalbuf[0] = '\0', literallen = 0)
46
static void addlit(char *ytext, int yleng);
47
static void addlitchar (unsigned char);
48
static void parse_include (void);
49
static void check_escape_warning(void);
50

M
Michael Meskes 已提交
51
char *token_start;
M
Michael Meskes 已提交
52
int state_before;
M
Marc G. Fournier 已提交
53

54 55 56 57 58 59 60
struct _yy_buffer 
{ 
	YY_BUFFER_STATE		buffer;
	long				lineno;
	char		  		*filename;
	struct _yy_buffer 	*next;
} *yy_buffer = NULL;
61

M
 
Marc G. Fournier 已提交
62 63
static char *old;

64 65 66
#define MAX_NESTED_IF 128
static short preproc_tos;
static short ifcond;
67 68 69 70
static struct _if_value 
{
	short condition;
	short else_branch;
71 72
} stacked_if_value[MAX_NESTED_IF];

73
%}
M
Michael Meskes 已提交
74

75 76
%option 8bit
%option never-interactive
77
%option nodefault
78 79
%option noyywrap

80
%option yylineno
81

M
 
Marc G. Fournier 已提交
82
%s C SQL incl def def_ident
M
Michael Meskes 已提交
83 84 85

/*
 * OK, here is a short description of lex/flex rules behavior.
M
Marc G. Fournier 已提交
86 87
 * The longest pattern which matches an input string is always chosen.
 * For equal-length patterns, the first occurring in the rules list is chosen.
M
Michael Meskes 已提交
88 89 90
 * INITIAL is the starting state, to which all non-conditional rules apply.
 * Exclusive states change parsing rules while the state is active.  When in
 * an exclusive state, only those rules defined for that state apply.
M
Marc G. Fournier 已提交
91
 *
M
Michael Meskes 已提交
92 93
 * We use exclusive states for quoted strings, extended comments,
 * and to eliminate parsing troubles for numeric strings.
M
Marc G. Fournier 已提交
94
 * Exclusive states:
M
Michael Meskes 已提交
95
 *	<xb> bit string literal
96 97 98 99
 *	<xc> extended C-style comments - thomas 1997-07-12
 *	<xd> delimited identifiers (double-quoted identifiers) - thomas 1997-10-27
 *	<xh> hexadecimal numeric string - thomas 1997-11-16
 *	<xq> quoted strings - thomas 1997-07-30
B
Bruce Momjian 已提交
100
 *  <xdolq> $foo$ quoted strings
M
Marc G. Fournier 已提交
101 102
 */

M
Michael Meskes 已提交
103
%x xb
M
Marc G. Fournier 已提交
104 105
%x xc
%x xd
106
%x xdc
M
Marc G. Fournier 已提交
107 108
%x xh
%x xq
109
%x xdolq
110 111 112
%x xpre
%x xcond
%x xskip
M
Marc G. Fournier 已提交
113

M
Michael Meskes 已提交
114
/* Bit string
M
Marc G. Fournier 已提交
115
 */
M
Michael Meskes 已提交
116 117
xbstart			[bB]{quote}
xbinside		[^']*
M
Marc G. Fournier 已提交
118

119
/* Hexadecimal number */
M
Marc G. Fournier 已提交
120
xhstart			[xX]{quote}
121
xhinside		[^']*
M
Marc G. Fournier 已提交
122

123
/* National character */
124
xnstart			[nN]{quote}
M
Michael Meskes 已提交
125

126
/* Quoted string that allows backslash escapes */
B
Bruce Momjian 已提交
127
xestart 		[eE]{quote}
128 129

/* C version of hex number */
130
xch				0[xX][0-9A-Fa-f]*
M
Michael Meskes 已提交
131

M
Marc G. Fournier 已提交
132
/* Extended quote
133
 * xqdouble implements embedded quote, ''''
M
Marc G. Fournier 已提交
134 135 136
 */
xqstart			{quote}
xqdouble		{quote}{quote}
M
Michael Meskes 已提交
137
xqinside		[^\\']+
138 139 140
xqescape		[\\][^0-7]
xqoctesc		[\\][0-7]{1,3}
xqhexesc		[\\]x[0-9A-Fa-f]{1,2}
M
Marc G. Fournier 已提交
141

142 143 144 145 146
/* $foo$ style quotes ("dollar quoting")
 * The quoted string starts with $foo$ where "foo" is an optional string
 * in the form of an identifier, except that it may not contain "$",
 * and extends to the first occurrence of an identical string.
 * There is *no* processing of the quoted text.
147 148 149
 *
 * {dolqfailed} is an error rule to avoid scanner backup when {dolqdelim}
 * fails to match its trailing "$".
150
 */
151 152 153 154
dolq_start		[A-Za-z\200-\377_]
dolq_cont		[A-Za-z\200-\377_0-9]
dolqdelim		\$({dolq_start}{dolq_cont}*)?\$
dolqfailed		\${dolq_start}{dolq_cont}*
M
Michael Meskes 已提交
155
dolqinside		[^$]+
156

157
/* Double quote
M
Marc G. Fournier 已提交
158 159 160 161 162
 * Allows embedded spaces and other special characters into identifiers.
 */
dquote			\"
xdstart			{dquote}
xdstop			{dquote}
B
Bruce Momjian 已提交
163
xddouble		{dquote}{dquote}
M
Michael Meskes 已提交
164
xdinside		[^"]+
M
Michael Meskes 已提交
165 166 167 168 169 170

/* special stuff for C strings */
xdcqq			\\\\
xdcqdq			\\\"
xdcother		[^"]
xdcinside		({xdcqq}|{xdcqdq}|{xdcother})
M
Marc G. Fournier 已提交
171

172 173
/* C-style comments
 *
M
Michael Meskes 已提交
174 175 176
 * The "extended comment" syntax closely resembles allowable operator syntax.
 * The tricky part here is to get lex to recognize a string starting with
 * slash-star as a comment, when interpreting it as an operator would produce
177
 * a longer match --- remember lex will prefer a longer match!	Also, if we
178 179
 * have something like plus-slash-star, lex will think this is a 3-character
 * operator whereas we want to see it as a + operator and a comment start.
M
Michael Meskes 已提交
180
 * The solution is two-fold:
181
 * 1. append {op_chars}* to xcstart so that it matches as much text as
182 183 184
 *	  {operator} would. Then the tie-breaker (first matching rule of same
 *	  length) ensures xcstart wins.  We put back the extra stuff with yyless()
 *	  in case it contains a star-slash that should terminate the comment.
M
Michael Meskes 已提交
185
 * 2. In the operator rule, check for slash-star within the operator, and
186 187
 *	  if found throw it back with yyless().  This handles the plus-slash-star
 *	  problem.
188
 * Dash-dash comments have similar interactions with the operator rule.
M
Marc G. Fournier 已提交
189
 */
190
xcstart			\/\*{op_chars}*
M
Michael Meskes 已提交
191
xcstop			\*+\/
192
xcinside		[^*/]+
M
Marc G. Fournier 已提交
193 194

digit			[0-9]
M
Michael Meskes 已提交
195 196
ident_start		[A-Za-z\200-\377_]
ident_cont		[A-Za-z\200-\377_0-9\$]
M
Marc G. Fournier 已提交
197

M
Michael Meskes 已提交
198
identifier		{ident_start}{ident_cont}*
M
Marc G. Fournier 已提交
199

200
array			({ident_cont}|{whitespace}|[\[\]\+\-\*\%\/\(\)\>\.])*
M
Marc G. Fournier 已提交
201 202
typecast		"::"

203 204
/*
 * "self" is the set of chars that should be returned as single-character
205
 * tokens.	"op_chars" is the set of chars that can make up "Op" tokens,
206 207 208 209 210 211 212
 * which can be one or more characters long (but if a single-char token
 * appears in the "self" set, it is not to be returned as an Op).  Note
 * that the sets overlap, but each has some chars that are not in the other.
 *
 * If you change either set, adjust the character lists appearing in the
 * rule for "operator"!
 */
M
Michael Meskes 已提交
213 214
self			[,()\[\].;\:\+\-\*\/\%\^\<\>\=]
op_chars		[\~\!\@\#\^\&\|\`\?\+\-\*\/\%\<\>\=]
215
operator		{op_chars}+
M
Marc G. Fournier 已提交
216

217
/* we no longer allow unary minus in numbers.
218
 * instead we pass it separately to parser. there it gets
219
 * coerced via doNegate() -- Leon aug 20 1999
220 221 222
 *
 * {realfail1} and {realfail2} are added to prevent the need for scanner
 * backup when the {real} rule fails to match completely.
M
Michael Meskes 已提交
223
 */
224

M
Michael Meskes 已提交
225 226
integer			{digit}+
decimal			(({digit}*\.{digit}+)|({digit}+\.{digit}*))
227 228 229
real			({integer}|{decimal})[Ee][-+]?{digit}+
realfail1		({integer}|{decimal})[Ee]
realfail2		({integer}|{decimal})[Ee][-+]
M
Marc G. Fournier 已提交
230 231 232

param			\${integer}

M
Michael Meskes 已提交
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
/*
 * In order to make the world safe for Windows and Mac clients as well as
 * Unix ones, we accept either \n or \r as a newline.  A DOS-style \r\n
 * sequence will be seen as two successive newlines, but that doesn't cause
 * any problems.  SQL92-style comments, which start with -- and extend to the
 * next newline, are treated as equivalent to a single whitespace character.
 *
 * NOTE a fine point: if there is no newline following --, we will absorb
 * everything to the end of the input as a comment.  This is correct.  Older
 * versions of Postgres failed to recognize -- as a comment if the input
 * did not end with a newline.
 *
 * XXX perhaps \f (formfeed) should be treated as a newline as well?
 */

M
Michael Meskes 已提交
248
ccomment		"//".*\n
M
Marc G. Fournier 已提交
249

250
space			[ \t\n\r\f]
M
Michael Meskes 已提交
251
horiz_space		[ \t\f]
252
newline			[\n\r]
M
Michael Meskes 已提交
253 254
non_newline		[^\n\r]

255
comment			("--"{non_newline}*)
M
Michael Meskes 已提交
256

257
whitespace		({space}+|{comment})
M
Michael Meskes 已提交
258 259 260 261 262 263 264 265 266

/*
 * SQL92 requires at least one newline in the whitespace separating
 * string literals that are to be concatenated.  Silly, but who are we
 * to argue?  Note that {whitespace_with_newline} should not have * after
 * it, whereas {whitespace} should generally have a * after it...
 */

horiz_whitespace	({horiz_space}|{comment})
267
whitespace_with_newline ({horiz_whitespace}*{newline}{whitespace}*)
M
Michael Meskes 已提交
268

269 270
quote			'
quotestop		{quote}{whitespace}*
271
quotecontinue	{quote}{whitespace_with_newline}{quote}
272 273
quotefail		{quote}{whitespace}*"-"

274 275 276 277
/* special characters for other dbms */
/* we have to react differently in compat mode */
informix_special	[\$]

M
Marc G. Fournier 已提交
278 279 280
other			.

/* some stuff needed for ecpg */
B
Bruce Momjian 已提交
281 282 283 284
exec			[eE][xX][eE][cC]
sql				[sS][qQ][lL]
define			[dD][eE][fF][iI][nN][eE]
include 		[iI][nN][cC][lL][uU][dD][eE]
M
Marc G. Fournier 已提交
285

B
Bruce Momjian 已提交
286 287 288 289 290
ifdef			[iI][fF][dD][eE][fF]
ifndef			[iI][fF][nN][dD][eE][fF]
else			[eE][lL][sS][eE]
elif			[eE][lL][iI][fF]
endif			[eE][nN][dD][iI][fF]
291

B
Bruce Momjian 已提交
292
struct			[sS][tT][rR][uU][cC][tT]
293

294
exec_sql		{exec}{space}*{sql}{space}*
M
Michael Meskes 已提交
295
ipdigit			({digit}|{digit}{digit}|{digit}{digit}{digit})
296
ip				{ipdigit}\.{ipdigit}\.{ipdigit}\.{ipdigit}
297

298 299 300
/* we might want to parse all cpp include files */
cppinclude 		{space}*#{include}{space}*

301 302
/* Take care of cpp lines, they may also be continuated */
cppline			{space}*#(.*\\{space})*.*{newline}
M
 
Marc G. Fournier 已提交
303

304
/*
305 306
 * Dollar quoted strings are totally opaque, and no escaping is done on them.
 * Other quoted strings must allow some special characters such as single-quote
307
 *	and newline.
308
 * Embedded single-quotes are implemented both in the SQL standard
309 310
 *	style of two adjacent single quotes "''" and in the Postgres/Java style
 *	of escaped-quote "\'".
M
Marc G. Fournier 已提交
311
 * Other embedded escaped characters are matched explicitly and the leading
312
 *	backslash is dropped from the string. - thomas 1997-09-24
M
Michael Meskes 已提交
313
 * Note that xcstart must appear before operator, as explained above!
314
 *	Also whitespace (comment) must appear before operator.
M
Marc G. Fournier 已提交
315 316
 */

317
%%
318 319

%{
320 321
		/* code to execute during start of each call of yylex() */
		token_start = NULL;
322 323
%}

M
Michael Meskes 已提交
324
<SQL>{whitespace}	{ /* ignore */ }
M
Marc G. Fournier 已提交
325

B
Bruce Momjian 已提交
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
{xcstart}		{
					token_start = yytext;
					state_before = YYSTATE;
					xcdepth = 0;
					BEGIN(xc);
					/* Put back any characters past slash-star; see above */
					yyless(2);
					fputs("/*", yyout);
				}
<xc>{xcstart}	{
					xcdepth++;
			 		/* Put back any characters past slash-star; see above */
			 		yyless(2);
					fputs("/*", yyout);
				}
341

B
Bruce Momjian 已提交
342 343 344 345 346 347
<xc>{xcstop}	{
					ECHO;
					if (xcdepth <= 0)
					{
						BEGIN(state_before);
						token_start = NULL;
348
					}
B
Bruce Momjian 已提交
349 350 351
					else
						xcdepth--;
				}
352

353 354
<xc>{xcinside}	{ ECHO; }
<xc>{op_chars}	{ ECHO; }
355
<xc>\*+ 		{ ECHO; }
356

357
<xc><<EOF>>		{ mmerror(PARSE_ERROR, ET_FATAL, "Unterminated /* comment"); }
358

M
Michael Meskes 已提交
359
<SQL>{xbstart}	{
360 361 362 363 364
					token_start = yytext;
					BEGIN(xb);
					startlit();
					addlitchar('b');
				}
365 366
<xb>{quotestop} |
<xb>{quotefail}	{
367 368 369 370 371 372 373
					yyless(1);
					BEGIN(SQL);
					if (literalbuf[strspn(literalbuf, "01") + 1] != '\0')
						mmerror(PARSE_ERROR, ET_ERROR, "invalid bit string input.");
					yylval.str = mm_strdup(literalbuf);
					return BCONST;
				}
M
Marc G. Fournier 已提交
374 375

<xh>{xhinside}	|
M
Michael Meskes 已提交
376
<xb>{xbinside}	{ addlit(yytext, yyleng); }
377 378
<xh>{quotecontinue}	|
<xb>{quotecontinue}	{ /* ignore */ }
379
<xb><<EOF>>		{ mmerror(PARSE_ERROR, ET_FATAL, "Unterminated bit string"); }
M
Marc G. Fournier 已提交
380

381 382 383 384 385 386
<SQL>{xhstart}	{
					token_start = yytext;
					BEGIN(xh);
					startlit();
					addlitchar('x');
				}
387 388 389 390 391 392 393
<xh>{quotestop}	|
<xh>{quotefail} 	{
				yyless(1);
				BEGIN(SQL);
				yylval.str = mm_strdup(literalbuf);
				return XCONST;
			}
394

395
<xh><<EOF>>		{ mmerror(PARSE_ERROR, ET_FATAL, "Unterminated hexadecimal integer"); }
M
Michael Meskes 已提交
396 397
<SQL>{xnstart}              {
				/* National character.
398 399 400
				 * Transfer it as-is to the backend.
				 */
		        token_start = yytext;
M
Michael Meskes 已提交
401 402 403
				BEGIN(xq);
				startlit();
			}
404
<C,SQL>{xqstart}	{
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
				warn_on_first_escape = true;
				token_start = yytext;
				state_before = YYSTATE;
				BEGIN(xq);
				startlit();
			}
<C,SQL>{xestart}	{
				warn_on_first_escape = false;
				token_start = yytext;
				state_before = YYSTATE;
				BEGIN(xq);
				startlit();
			}
<xq>{quotestop} |
<xq>{quotefail}		{
				yyless(1);
				BEGIN(state_before);
				yylval.str = mm_strdup(literalbuf);
				return SCONST;
			}
425 426
<xq>{xqdouble}		{ addlitchar('\''); }
<xq>{xqinside}		{ addlit(yytext, yyleng); }
427 428 429 430 431 432 433 434 435 436 437 438 439
<xq>{xqescape}  	{ 
				check_escape_warning();
				addlit(yytext, yyleng);
			}
<xq>{xqoctesc}		{ 
				check_escape_warning();
				addlit(yytext, yyleng);
			}
<xq>{xqhexesc}		{ 
				check_escape_warning();
				addlit(yytext, yyleng);
			}
<xq>{quotecontinue}	{ /* ignore */ }
M
Michael Meskes 已提交
440
<xq>{other}		{
441 442 443
			   /* This is only needed for \ just before EOF */
			   addlitchar(yytext[0]);
			}
444
<xq><<EOF>>		{ mmerror(PARSE_ERROR, ET_FATAL, "Unterminated quoted string"); }
445 446 447 448 449 450
<SQL>{dolqfailed}	{
				/* throw back all but the initial "$" */
				yyless(1);
				/* and treat it as {other} */
				return yytext[0];	
			}
451 452 453 454 455
<SQL>{dolqdelim}        {
				token_start = yytext;
				dolqstart = mm_strdup(yytext);
				BEGIN(xdolq);
				startlit();
M
Michael Meskes 已提交
456
				addlit(yytext, yyleng);
457 458 459 460
			}
<xdolq>{dolqdelim}      {
				if (strcmp(yytext, dolqstart) == 0)
				{
M
Michael Meskes 已提交
461
					addlit(yytext, yyleng);
462 463 464
					free(dolqstart);
					BEGIN(SQL);
					yylval.str = mm_strdup(literalbuf);
M
Michael Meskes 已提交
465
					return DOLCONST;
466 467 468
				}
				else
				{
469 470 471 472 473 474 475
			        /*
			         * When we fail to match $...$ to dolqstart, transfer
			         * the $... part to the output, but put back the final
			         * $ for rescanning.  Consider $delim$...$junk$delim$
			         */
			        addlit(yytext, yyleng-1);
			        yyless(yyleng-1);
476 477
				}
			}
478 479
<xdolq>{dolqinside} 	{ addlit(yytext, yyleng); }
<xdolq>{dolqfailed}	{ addlit(yytext, yyleng); }
M
Michael Meskes 已提交
480
<xdolq>{other}		{
481
				/* single quote or dollar sign */
482 483
				addlitchar(yytext[0]);
			}
M
Michael Meskes 已提交
484
<xdolq><<EOF>> 		{ yyerror("unterminated dollar-quoted string"); }
485 486 487 488 489
<SQL>{xdstart}		{
						state_before = YYSTATE;
						BEGIN(xd);
						startlit();
					}
M
Michael Meskes 已提交
490
<xd>{xdstop}		{
491
						BEGIN(state_before);
492 493
						if (literallen == 0)
							mmerror(PARSE_ERROR, ET_ERROR, "zero-length delimited identifier");
494
						/* The backend will truncate the idnetifier here. We do not as it does not change the result. */
495 496 497 498 499 500 501 502
						yylval.str = mm_strdup(literalbuf);
						return CSTRING;
					}
<xdc>{xdstop}		{
						BEGIN(state_before);
						yylval.str = mm_strdup(literalbuf);
						return CSTRING;
					}
503
<xd>{xddouble}		{ addlitchar('"'); }
504
<xd>{xdinside}		{ addlit(yytext, yyleng); }
505
<xd,xdc><<EOF>>		{ mmerror(PARSE_ERROR, ET_FATAL, "Unterminated quoted identifier"); }
506 507 508 509
<C,SQL>{xdstart}	{
						state_before = YYSTATE;
						BEGIN(xdc);
						startlit();
M
Michael Meskes 已提交
510
					}
511 512
<xdc>{xdcinside}	{ addlit(yytext, yyleng); }
<SQL>{typecast}		{ return TYPECAST; }
513 514
<SQL>{informix_special}	{
			  /* are we simulating Informix? */
515 516 517 518 519 520 521
				if (INFORMIX_MODE)
				{
					unput(':');
				}
				else
					return yytext[0];
				}
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
<SQL>{self}			{ /*
					   * We may find a ';' inside a structure
					   * definition in a TYPE or VAR statement.
					   * This is not an EOL marker.
					   */
					  if (yytext[0] == ';' && struct_level == 0)
						 BEGIN C;
					  return yytext[0];
					}
<SQL>{operator}		{
						/*
						 * Check for embedded slash-star or dash-dash; those
						 * are comment starts, so operator must stop there.
						 * Note that slash-star or dash-dash at the first
						 * character will match a prior rule, not this one.
						 */
						int		nchars = yyleng;
539 540
						char   *slashstar = strstr(yytext, "/*");
						char   *dashdash = strstr(yytext, "--");
541 542

						if (slashstar && dashdash)
543
						{
544 545 546
							/* if both appear, take the first one */
							if (slashstar > dashdash)
								slashstar = dashdash;
547
						}
548 549 550
						else if (!slashstar)
							slashstar = dashdash;
						if (slashstar)
551
							nchars = slashstar - yytext;
552 553

						/*
554
						 * For SQL compatibility, '+' and '-' cannot be the
555
						 * last char of a multi-char operator unless the operator
556
						 * contains chars that are not in SQL operators.
557 558
						 * The idea is to lex '=-' as two operators, but not
						 * to forbid operator names like '?-' that could not be
559
						 * sequences of SQL operators.
M
Michael Meskes 已提交
560
						 */
561 562 563 564 565 566 567 568
						while (nchars > 1 &&
							   (yytext[nchars-1] == '+' ||
								yytext[nchars-1] == '-'))
						{
							int		ic;

							for (ic = nchars-2; ic >= 0; ic--)
							{
M
Michael Meskes 已提交
569
								if (strchr("~!@#^&|`?%", yytext[ic]))
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
									break;
							}
							if (ic >= 0)
								break; /* found a char that makes it OK */
							nchars--; /* else remove the +/-, and check again */
						}

						if (nchars < yyleng)
						{
							/* Strip the unwanted chars from the token */
							yyless(nchars);
							/*
							 * If what we have left is only one char, and it's
							 * one of the characters matching "self", then
							 * return it as a character token the same way
							 * that the "self" rule would have.
							 */
							if (nchars == 1 &&
M
Michael Meskes 已提交
588
								strchr(",()[].;:+-*/%^<>=", yytext[0]))
589 590 591 592
								return yytext[0];
						}

						/* Convert "!=" operator to "<>" for compatibility */
593
						if (strcmp(yytext, "!=") == 0)
594 595
							yylval.str = mm_strdup("<>");
						else
596
							yylval.str = mm_strdup(yytext);
597
						return Op;
M
Michael Meskes 已提交
598
					}
599
<SQL>{param}		{
600
						yylval.ival = atol(yytext+1);
601 602 603 604 605
						return PARAM;
					}
<C,SQL>{integer}	{
						long val;
						char* endptr;
M
Michael Meskes 已提交
606

M
Marc G. Fournier 已提交
607
						errno = 0;
608 609 610 611 612 613 614 615 616
						val = strtol((char *)yytext, &endptr,10);
						if (*endptr != '\0' || errno == ERANGE
#ifdef HAVE_LONG_INT_64
							/* if long > 32 bits, check for overflow of int4 */
							|| val != (long) ((int32) val)
#endif
							)
						{
							errno = 0;
617
							yylval.str = mm_strdup(yytext);
618 619 620 621 622 623
							return FCONST;
						}
						yylval.ival = val;
						return ICONST;
					}
<SQL>{ip}			{
624
						yylval.str = mm_strdup(yytext);
625
						return IP;
M
Michael Meskes 已提交
626 627
				}
<C,SQL>{decimal}	{
628
						yylval.str = mm_strdup(yytext);
629
						return FCONST;
630
			}
631
<C,SQL>{real}		{
632
						yylval.str = mm_strdup(yytext);
M
Michael Meskes 已提交
633
						return FCONST;
634 635
			}
<SQL>{realfail1}	{
636 637 638 639
						yyless(yyleng-1);
						yylval.str = mm_strdup(yytext);
						return FCONST;
					}
640
<SQL>{realfail2}	{
641 642 643 644
						yyless(yyleng-2);
						yylval.str = mm_strdup(yytext);
						return FCONST;
					}
645
<SQL>:{identifier}((("->"|\.){identifier})|(\[{array}\]))*	{
646
						yylval.str = mm_strdup(yytext+1);
647 648
						return(CVARIABLE);
					}
M
Marc G. Fournier 已提交
649
<SQL>{identifier}	{
650 651
						ScanKeyword    *keyword;
						struct _defines *ptr;
M
Michael Meskes 已提交
652
						
653 654
						/* How about a DEFINE? */
						for (ptr = defines; ptr; ptr = ptr->next)
M
Marc G. Fournier 已提交
655
						{
M
Michael Meskes 已提交
656
							if (strcmp(yytext, ptr->old) == 0 && ptr->used == NULL)
657 658
							{
								struct _yy_buffer *yb;
M
 
Marc G. Fournier 已提交
659

660 661 662 663 664
								yb = mm_alloc(sizeof(struct _yy_buffer));

								yb->buffer =  YY_CURRENT_BUFFER;
								yb->lineno = yylineno;
								yb->filename = mm_strdup(input_filename);
665
								yb->next = yy_buffer;
M
Michael Meskes 已提交
666
								
667
								ptr->used = yy_buffer = yb;
M
 
Marc G. Fournier 已提交
668

669 670 671 672
								yy_scan_string(ptr->new);
								break;
							}
						}
673 674 675 676 677 678
						if (ptr == NULL)
						{
							/* Is it an SQL keyword? */
							keyword = ScanKeywordLookup(yytext);
							if (keyword != NULL)
								return keyword->value;
679

680 681 682 683
							/* Is it an ECPG keyword? */
							keyword = ScanECPGKeywordLookup( yytext);
							if (keyword != NULL)
								return keyword->value;
684

685 686 687 688
							/* Is it a C keyword? */
							keyword = ScanCKeywordLookup(yytext);
							if (keyword != NULL)
								return keyword->value;
689

690 691 692
							/*
							 * None of the above.  Return it as an identifier.
							 *
M
Michael Meskes 已提交
693
							 * The backend will attempt to truncate and case-fold
694 695 696 697
							 * the identifier, but I see no good reason for ecpg
							 * to do so; that's just another way that ecpg could get
							 * out of step with the backend.
							 */
M
Michael Meskes 已提交
698 699
							yylval.str = mm_strdup(yytext);
							return IDENT;
M
Marc G. Fournier 已提交
700 701
						}
					}
702 703
<SQL>{other}		{ return yytext[0]; }
<C>{exec_sql}		{ BEGIN SQL; return SQL_START; }
704
<C>{informix_special}	{ 
705 706 707 708 709 710 711 712 713 714
						/* are we simulating Informix? */
						if (INFORMIX_MODE)
						{
							BEGIN SQL;
							return SQL_START;
						}
						else
							return S_ANYTHING;
					 }
<C>{ccomment}		{ ECHO; }
M
Michael Meskes 已提交
715
<C>{xch}			{
716
						char* endptr;
M
Michael Meskes 已提交
717 718

						errno = 0;
M
Michael Meskes 已提交
719
						yylval.ival = strtoul((char *)yytext,&endptr,16);
720 721 722
						if (*endptr != '\0' || errno == ERANGE)
						{
							errno = 0;
723
							yylval.str = mm_strdup(yytext);
724 725 726 727
							return SCONST;
						}
						return ICONST;
					}
728
<C>{cppinclude}		{
729 730 731 732 733 734 735 736 737 738 739
						if (system_includes)
						{
							BEGIN(incl);
						}
						else
					 	{
							yylval.str = mm_strdup(yytext);
							return(CPP_LINE);
					  	}
					}
<C,SQL>{cppline}	{
740
						yylval.str = mm_strdup(yytext);
741
						return(CPP_LINE);
M
Michael Meskes 已提交
742
					}
743 744
<C>{identifier} 	{
						ScanKeyword		*keyword;
745
						struct _defines *ptr;
M
 
Marc G. Fournier 已提交
746

747
						if (INFORMIX_MODE)
M
 
Marc G. Fournier 已提交
748
						{
749 750 751 752 753 754 755
							/* Informix uses SQL defines only in SQL space */
							ptr = NULL;
						}
						else
						{
							/* is it a define? */
							for (ptr = defines; ptr; ptr = ptr->next)
M
 
Marc G. Fournier 已提交
756
							{
757 758 759
								if (strcmp(yytext, ptr->old) == 0 && ptr->used == NULL)
								{
									struct _yy_buffer *yb;
M
 
Marc G. Fournier 已提交
760

761
									yb = mm_alloc(sizeof(struct _yy_buffer));
M
 
Marc G. Fournier 已提交
762

763 764 765
									yb->buffer =  YY_CURRENT_BUFFER;
									yb->lineno = yylineno;
									yb->filename = mm_strdup(input_filename);
766
									yb->next = yy_buffer;
M
 
Marc G. Fournier 已提交
767

768
									ptr->used = yy_buffer = yb;
M
 
Marc G. Fournier 已提交
769

770 771 772
									yy_scan_string(ptr->new);
									break;
								}
773
							}
774 775 776 777 778 779 780
						}

						if (ptr == NULL)
						{
							keyword = ScanCKeywordLookup(yytext);
							if (keyword != NULL)
								return keyword->value;
781 782
							else
							{
783
								yylval.str = mm_strdup(yytext);
784
								return IDENT;
M
 
Marc G. Fournier 已提交
785 786
							}
						}
M
Marc G. Fournier 已提交
787
					}
788
<C>":"				{ return(':'); }
789 790 791 792 793 794 795 796 797
<C>";"				{ return(';'); }
<C>","				{ return(','); }
<C>"*"				{ return('*'); }
<C>"%"				{ return('%'); }
<C>"/"				{ return('/'); }
<C>"+"				{ return('+'); }
<C>"-"				{ return('-'); }
<C>"("				{ return('('); }
<C>")"				{ return(')'); }
M
Michael Meskes 已提交
798
<C,xskip>{space}		{ ECHO; }
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820
<C>\{				{ return('{'); }
<C>\}				{ return('}'); }
<C>\[				{ return('['); }
<C>\]				{ return(']'); }
<C>\=				{ return('='); }
<C>"->"				{ return(S_MEMBER); }
<C>">>"				{ return(S_RSHIFT); }
<C>"<<"				{ return(S_LSHIFT); }
<C>"||"				{ return(S_OR); }
<C>"&&"				{ return(S_AND); }
<C>"++"				{ return(S_INC); }
<C>"--"				{ return(S_DEC); }
<C>"=="				{ return(S_EQUAL); }
<C>"!="				{ return(S_NEQUAL); }
<C>"+="				{ return(S_ADD); }
<C>"-="				{ return(S_SUB); }
<C>"*="				{ return(S_MUL); }
<C>"/="				{ return(S_DIV); }
<C>"%="				{ return(S_MOD); }
<C>"->*"			{ return(S_MEMPOINT); }
<C>".*"				{ return(S_DOTPOINT); }
<C>{other}			{ return S_ANYTHING; }
821

822
<C>{exec_sql}{define}{space}*	{ BEGIN(def_ident); }
823 824
<C>{informix_special}{define}{space}*	{
						/* are we simulating Informix? */
825
						if (INFORMIX_MODE)
826 827 828 829 830
						{
							BEGIN(def_ident);
						}
						else
						{
831
							yyless(1);
832 833 834
							return (S_ANYTHING);
						}
					}
835
<C>{exec_sql}{include}{space}*	{ BEGIN(incl); }
836 837
<C>{informix_special}{include}{space}* { 
					  /* are we simulating Informix? */
838
					  if (INFORMIX_MODE)
839
					  {
840
						  BEGIN(incl);
841 842 843
					  }
					  else
					  {
844 845
						  yyless(1);
						  return (S_ANYTHING);
846 847
					  }
					}
848
<C,xskip>{exec_sql}{ifdef}{space}*	{ ifcond = TRUE; BEGIN(xcond); }
849 850
<C,xskip>{informix_special}{ifdef}{space}* { 
					  /* are we simulating Informix? */
851
					  if (INFORMIX_MODE)
852
					  {
853 854
						  ifcond = TRUE;
						  BEGIN(xcond);
855 856 857
					  }
					  else
					  {
858 859
						  yyless(1);
						  return (S_ANYTHING);
860 861
					  }
					}
862
<C,xskip>{exec_sql}{ifndef}{space}* { ifcond = FALSE; BEGIN(xcond); }
863 864
<C,xskip>{informix_special}{ifndef}{space}* { 
					  /* are we simulating Informix? */
865
					  if (INFORMIX_MODE)
866
					  {
867 868
						  ifcond = FALSE;
						  BEGIN(xcond);
869 870 871
					  }
					  else
					  {
872 873
						  yyless(1);
						  return (S_ANYTHING);
874 875
					  }
					}
876
<C,xskip>{exec_sql}{elif}{space}*	{	/* pop stack */
877
						if ( preproc_tos == 0 ) {
878
							mmerror(PARSE_ERROR, ET_FATAL, "Missing matching 'EXEC SQL IFDEF / EXEC SQL IFNDEF'");
879
						}
880 881 882 883
						else if ( stacked_if_value[preproc_tos].else_branch )
							mmerror(PARSE_ERROR, ET_FATAL, "Missing 'EXEC SQL ENDIF;'");
						else
							preproc_tos--;
884 885 886

						ifcond = TRUE; BEGIN(xcond);
					}
887
<C,xskip>{informix_special}{elif}{space}* { 
888 889 890 891
					/* are we simulating Informix? */
					if (INFORMIX_MODE)
					{
						if (preproc_tos == 0)
892
							mmerror(PARSE_ERROR, ET_FATAL, "Missing matching 'EXEC SQL IFDEF / EXEC SQL IFNDEF'");
893
						else if (stacked_if_value[preproc_tos].else_branch)
894 895 896 897
							mmerror(PARSE_ERROR, ET_FATAL, "Missing 'EXEC SQL ENDIF;'");
						else
							preproc_tos--;

898 899
						ifcond = TRUE;
						BEGIN(xcond);
900
					}
901 902 903 904 905 906
					else
					{
						yyless(1);
						return (S_ANYTHING);
					}
				}
907

908
<C,xskip>{exec_sql}{else}{space}*";" {	/* only exec sql endif pops the stack, so take care of duplicated 'else' */
909 910 911 912 913 914
					if (stacked_if_value[preproc_tos].else_branch)
						mmerror(PARSE_ERROR, ET_FATAL, "Duplicated 'EXEC SQL ELSE;'");
					else
					{
						stacked_if_value[preproc_tos].else_branch = TRUE;
						stacked_if_value[preproc_tos].condition =
915
							(stacked_if_value[preproc_tos-1].condition &&
916
							 !stacked_if_value[preproc_tos].condition);
917

918 919 920 921
						if (stacked_if_value[preproc_tos].condition)
							BEGIN(C);
						else
							BEGIN(xskip);
922
					}
923
				}
924
<C,xskip>{informix_special}{else}{space}*	{
925 926 927 928
					/* are we simulating Informix? */
					if (INFORMIX_MODE)
					{
						if (stacked_if_value[preproc_tos].else_branch)
929
							mmerror(PARSE_ERROR, ET_FATAL, "Duplicated 'EXEC SQL ELSE;'");
930 931
						else
						{
932 933 934
							stacked_if_value[preproc_tos].else_branch = TRUE;
							stacked_if_value[preproc_tos].condition =
							(stacked_if_value[preproc_tos-1].condition &&
935
							 !stacked_if_value[preproc_tos].condition);
936

937
							if (stacked_if_value[preproc_tos].condition)
938 939 940 941 942
								BEGIN(C);
							else
								BEGIN(xskip);
						}
					}
943 944 945 946
					else
					{
						yyless(1);
						return (S_ANYTHING);
947
					}
948 949 950 951 952 953 954 955 956 957 958 959
				}
<C,xskip>{exec_sql}{endif}{space}*";" {
					if (preproc_tos == 0)
						mmerror(PARSE_ERROR, ET_FATAL, "Unmatched 'EXEC SQL ENDIF;'");
					else
						preproc_tos--;

					if (stacked_if_value[preproc_tos].condition)
					   BEGIN(C);
					else
					   BEGIN(xskip);
				}
M
Michael Meskes 已提交
960
<C,xskip>{informix_special}{endif}{space}*";"	{
961 962 963 964
					/* are we simulating Informix? */
					if (INFORMIX_MODE)
					{
						if (preproc_tos == 0)
965 966 967 968
							mmerror(PARSE_ERROR, ET_FATAL, "Unmatched 'EXEC SQL ENDIF;'");
						else
							preproc_tos--;

969 970
						if (stacked_if_value[preproc_tos].condition)
							BEGIN(C);
971
						else
972 973 974 975 976 977
							BEGIN(xskip);
					}
					else
					{
						yyless(1);
						return (S_ANYTHING);
978
					}
979
				}
980

981
<xskip>{other}		{ /* ignore */ }
982

983
<xcond>{identifier}{space}*";" {
984 985 986 987 988 989
					if (preproc_tos >= MAX_NESTED_IF-1)
						mmerror(PARSE_ERROR, ET_FATAL, "Too many nested 'EXEC SQL IFDEF' conditions");
					else 
					{
						struct _defines *defptr;
						unsigned int i;
990

991 992 993 994 995 996 997 998 999 1000 1001 1002
						/*
						 *	Skip the ";" and trailing whitespace. Note that yytext
						 *	contains at least one non-space character plus the ";"
						 */
						for (i = strlen(yytext)-2;
							 i > 0 && isspace((unsigned char) yytext[i]);
							 i-- )
							;
						yytext[i+1] = '\0';

						for (defptr = defines;
							 defptr != NULL && strcmp(yytext, defptr->old) != 0;
1003
							 defptr = defptr->next);
1004 1005 1006 1007 1008

						preproc_tos++;
						stacked_if_value[preproc_tos].else_branch = FALSE;
						stacked_if_value[preproc_tos].condition =
						(defptr ? ifcond : !ifcond) && stacked_if_value[preproc_tos-1].condition;
1009 1010
					}

1011 1012 1013 1014 1015 1016
					if (stacked_if_value[preproc_tos].condition)
						BEGIN C;
					else
						BEGIN(xskip);
				}

1017 1018 1019 1020
<xcond>{other}	{
			mmerror(PARSE_ERROR, ET_FATAL, "Missing identifier in 'EXEC SQL IFDEF' command");
			yyterminate();
		}
1021
<def_ident>{identifier} {
M
 
Marc G. Fournier 已提交
1022
				old = mm_strdup(yytext);
M
 
Marc G. Fournier 已提交
1023
				BEGIN(def);
1024
				startlit();
M
 
Marc G. Fournier 已提交
1025
			}
1026 1027 1028 1029
<def_ident>{other}	{
			mmerror(PARSE_ERROR, ET_FATAL, "Missing identifier in 'EXEC SQL DEFINE' command");
			yyterminate();
		}
1030
<def>{space}*";"	{
1031
						struct _defines *ptr, *this;
1032

1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
						for (ptr = defines; ptr != NULL; ptr = ptr->next)
						{
							 if (strcmp(old, ptr->old) == 0)
							 {
								free(ptr->new);
								ptr->new = mm_strdup(literalbuf);
							 }
						}
						if (ptr == NULL)
						{
M
Michael Meskes 已提交
1043
							this = (struct _defines *) mm_alloc(sizeof(struct _defines));
1044

M
Michael Meskes 已提交
1045 1046 1047
							/* initial definition */
							this->old = old;
							this->new = mm_strdup(literalbuf);
1048
							this->next = defines;
M
Michael Meskes 已提交
1049
							this->used = NULL;
1050 1051
							defines = this;
						}
1052

1053 1054 1055
						BEGIN(C);
					}
<def>[^;]			{ addlit(yytext, yyleng); }
1056 1057
<incl>\<[^\>]+\>{space}*";"?		{	parse_include(); }
<incl>{dquote}{xdinside}{dquote}{space}*";"?	{	parse_include(); }
1058
<incl>[^;\<\>\"]+";"		{ parse_include(); }
1059 1060 1061 1062
<incl>{other}	{
			mmerror(PARSE_ERROR, ET_FATAL, "Incorrect 'EXEC SQL INCLUDE' command");
			yyterminate();
		}
1063 1064

<<EOF>>				{
1065 1066
			  		if (yy_buffer == NULL)
					{
1067 1068 1069 1070 1071
				  		if ( preproc_tos > 0 ) 
						{
					  		preproc_tos = 0;
							mmerror(PARSE_ERROR, ET_FATAL, "Missing 'EXEC SQL ENDIF;'");
				  		}
1072 1073 1074 1075 1076 1077 1078
						yyterminate();
					}
			  		else
			  		{
						struct _yy_buffer *yb = yy_buffer;
						int i;
						struct _defines *ptr;
1079

1080 1081 1082 1083 1084 1085 1086 1087 1088
						for (ptr = defines; ptr; ptr = ptr->next)
							if (ptr->used == yy_buffer)
							{
								ptr->used = NULL;
								break;
							}
								
						if (yyin != NULL)
							fclose(yyin);
1089

1090 1091
						yy_delete_buffer( YY_CURRENT_BUFFER );
						yy_switch_to_buffer(yy_buffer->buffer);
1092

1093
						yylineno = yy_buffer->lineno;
1094

1095 1096
						/* We have to output the filename only if we change files here */
						i = strcmp(input_filename, yy_buffer->filename);
1097

1098 1099
						free(input_filename);
						input_filename = yy_buffer->filename;
1100

1101 1102
						yy_buffer = yy_buffer->next;
						free(yb);
1103

1104 1105 1106 1107 1108
						if (i != 0)
							output_line_number();
						
			  		}
				}
1109 1110
%%
void
1111
lex_init(void)
1112
{
1113 1114 1115
	braces_open = 0;

	preproc_tos = 0;
M
Michael Meskes 已提交
1116
	yylineno = 1;
1117 1118 1119
	ifcond = TRUE;
	stacked_if_value[preproc_tos].condition = ifcond;
	stacked_if_value[preproc_tos].else_branch = FALSE;
1120 1121 1122 1123 1124 1125 1126 1127 1128

	/* initialize literal buffer to a reasonable but expansible size */
	if (literalbuf == NULL)
	{
		literalalloc = 128;
		literalbuf = (char *) malloc(literalalloc);
	}
	startlit();

1129
	BEGIN C;
1130 1131
}

1132 1133 1134 1135 1136 1137
static void
addlit(char *ytext, int yleng)
{
	/* enlarge buffer if needed */
	if ((literallen+yleng) >= literalalloc)
	{
1138
		do 
1139
			literalalloc *= 2;
1140
		while ((literallen+yleng) >= literalalloc);
1141 1142
		literalbuf = (char *) realloc(literalbuf, literalalloc);
	}
1143 1144
	/* append new data, add trailing null */
	memcpy(literalbuf+literallen, ytext, yleng);
1145
	literallen += yleng;
1146
	literalbuf[literallen] = '\0';
1147 1148
}

1149 1150
static void
addlitchar(unsigned char ychar)
1151
{
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
	/* enlarge buffer if needed */
        if ((literallen+1) >= literalalloc)
        {
                literalalloc *= 2;
                literalbuf = (char *) realloc(literalbuf, literalalloc);
        }
	/* append new data, add trailing null */
	literalbuf[literallen] = ychar;
	literallen += 1;
	literalbuf[literallen] = '\0';
}
1163

1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185
static void
parse_include(void)
{
	/* got the include file name */
	struct _yy_buffer *yb;
  	struct _include_path *ip;
  	char inc_file[MAXPGPATH];
  	unsigned int i;

  	yb = mm_alloc(sizeof(struct _yy_buffer));

  	yb->buffer =	YY_CURRENT_BUFFER;
  	yb->lineno = yylineno;
  	yb->filename = input_filename;
  	yb->next = yy_buffer;

  	yy_buffer = yb;

  	/*
	 * skip the ";" if there is one and trailing whitespace. Note that
	 * yytext contains at least one non-space character plus the ";" 
	 */
1186 1187 1188 1189
  	for (i = strlen(yytext)-2;
		 i > 0 && isspace((unsigned char) yytext[i]);
		 i--)
		;
1190 1191 1192 1193 1194 1195 1196 1197 1198 1199

	if (yytext[i] == ';')
		i--;

	yytext[i+1] = '\0';
	
	yyin = NULL;

	/* If file name is enclosed in '"' remove these and look only in '.' */
	/* Informix does look into all include paths though, except filename starts with '/' */
1200
	if (yytext[0] == '"' && yytext[i] == '"' &&
1201
	    ((compat != ECPG_COMPAT_INFORMIX && compat != ECPG_COMPAT_INFORMIX_SE) || yytext[1] == '/'))
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
	{
		yytext[i] = '\0';
		memmove(yytext, yytext+1, strlen(yytext));
	
		strncpy(inc_file, yytext, sizeof(inc_file));
		yyin = fopen(inc_file, "r");
		if (!yyin)
		{
			if (strcmp(inc_file + strlen(inc_file) - 2, ".h"))
			{
				strcat(inc_file, ".h");
				yyin = fopen(inc_file, "r");
			}
		}
		
	}
	else
	{
		if ((yytext[0] == '"' && yytext[i] == '"') || (yytext[0] == '<' && yytext[i] == '>'))
		{
			yytext[i] = '\0';
			memmove(yytext, yytext+1, strlen(yytext));
		}
		
	  	for (ip = include_paths; yyin == NULL && ip != NULL; ip = ip->next)
	  	{
			if (strlen(ip->path) + strlen(yytext) + 3 > MAXPGPATH)
			{
				fprintf(stderr, "Error: Path %s/%s is too long in line %d, skipping.\n", ip->path, yytext, yylineno);
				continue;
			}
			snprintf (inc_file, sizeof(inc_file), "%s/%s", ip->path, yytext);
			yyin = fopen(inc_file, "r");
			if (!yyin)
			{
				if (strcmp(inc_file + strlen(inc_file) - 2, ".h"))
				{
					strcat(inc_file, ".h");
					yyin = fopen( inc_file, "r" );
				}
			}
		}
	}
	if (!yyin)
M
Michael Meskes 已提交
1246
		mmerror(NO_INCLUDE_FILE, ET_FATAL, "Cannot open include file %s in line %d\n", yytext, yylineno);
1247 1248 1249 1250 1251 1252 1253 1254

	input_filename = mm_strdup(inc_file);
	yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE ));
	yylineno = 1;
	output_line_number();

  	BEGIN C;
}
1255 1256 1257 1258 1259 1260

static void
check_escape_warning(void)
{
	if (warn_on_first_escape && escape_string_warning)
	       	mmerror (PARSE_ERROR, ET_WARNING, "nonstandard use of escape in a string literal");
1261
	warn_on_first_escape = false;   /* warn only once per string */
1262
}