20
20
#include " utils/guc.h"
21
21
22
22
23
- /* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
23
+ /*
24
+ * flex emits a yy_fatal_error() function that it calls in response to
25
+ * critical errors like malloc failure, file I/O errors, and detection of
26
+ * internal inconsistency. That function prints a message and calls exit().
27
+ * Mutate it to instead call our handler, which jumps out of the parser.
28
+ */
24
29
#undef fprintf
25
- #define fprintf (file, fmt, msg ) ereport(ERROR, (errmsg_internal( " %s " , msg)) )
30
+ #define fprintf (file, fmt, msg ) GUC_flex_fatal( msg)
26
31
27
32
enum {
28
33
GUC_ID = 1 ,
@@ -37,10 +42,13 @@ enum {
37
42
};
38
43
39
44
static unsigned int ConfigFileLineno;
45
+ static const char *GUC_flex_fatal_errmsg;
46
+ static sigjmp_buf *GUC_flex_fatal_jmp;
40
47
41
48
/* flex fails to supply a prototype for yylex, so provide one */
42
49
int GUC_yylex (void );
43
50
51
+ static int GUC_flex_fatal (const char *msg);
44
52
static char *GUC_scanstr (const char *s);
45
53
46
54
%}
@@ -436,6 +444,22 @@ ParseConfigFile(const char *config_file, const char *calling_file, bool strict,
436
444
return OK;
437
445
}
438
446
447
+ /*
448
+ * Flex fatal errors bring us here. Stash the error message and jump back to
449
+ * ParseConfigFp(). Assume all msg arguments point to string constants; this
450
+ * holds for flex 2.5.31 (earliest we support) and flex 2.5.35 (latest as of
451
+ * this writing). Otherwise, we would need to copy the message.
452
+ *
453
+ * We return "int" since this takes the place of calls to fprintf().
454
+ */
455
+ static int
456
+ GUC_flex_fatal (const char *msg)
457
+ {
458
+ GUC_flex_fatal_errmsg = msg;
459
+ siglongjmp (*GUC_flex_fatal_jmp, 1 );
460
+ return 0 ; /* keep compiler quiet */
461
+ }
462
+
439
463
/*
440
464
* Read and parse a single configuration file. This function recurses
441
465
* to handle "include" directives.
@@ -464,19 +488,38 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
464
488
ConfigVariable **head_p, ConfigVariable **tail_p)
465
489
{
466
490
bool OK = true ;
467
- YY_BUFFER_STATE lex_buffer;
491
+ unsigned int save_ConfigFileLineno = ConfigFileLineno;
492
+ sigjmp_buf *save_GUC_flex_fatal_jmp = GUC_flex_fatal_jmp;
493
+ sigjmp_buf flex_fatal_jmp;
494
+ volatile YY_BUFFER_STATE lex_buffer = NULL ;
468
495
int errorcount;
469
496
int token;
470
497
498
+ if (sigsetjmp (flex_fatal_jmp, 1 ) == 0 )
499
+ GUC_flex_fatal_jmp = &flex_fatal_jmp;
500
+ else
501
+ {
502
+ /*
503
+ * Regain control after a fatal, internal flex error. It may have
504
+ * corrupted parser state. Consequently, abandon the file, but trust
505
+ * that the state remains sane enough for yy_delete_buffer().
506
+ */
507
+ elog (elevel, " %s at file \" %s\" line %u" ,
508
+ GUC_flex_fatal_errmsg, config_file, ConfigFileLineno);
509
+
510
+ OK = false ;
511
+ goto cleanup;
512
+ }
513
+
471
514
/*
472
515
* Parse
473
516
*/
474
- lex_buffer = yy_create_buffer (fp, YY_BUF_SIZE);
475
- yy_switch_to_buffer (lex_buffer);
476
-
477
517
ConfigFileLineno = 1 ;
478
518
errorcount = 0 ;
479
519
520
+ lex_buffer = yy_create_buffer (fp, YY_BUF_SIZE);
521
+ yy_switch_to_buffer (lex_buffer);
522
+
480
523
/* This loop iterates once per logical line */
481
524
while ((token = yylex ()))
482
525
{
@@ -526,14 +569,11 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
526
569
* An include_if_exists directive isn't a variable and should be
527
570
* processed immediately.
528
571
*/
529
- unsigned int save_ConfigFileLineno = ConfigFileLineno;
530
-
531
572
if (!ParseConfigFile (opt_value, config_file, false ,
532
573
depth + 1 , elevel,
533
574
head_p, tail_p))
534
575
OK = false ;
535
576
yy_switch_to_buffer (lex_buffer);
536
- ConfigFileLineno = save_ConfigFileLineno;
537
577
pfree (opt_name);
538
578
pfree (opt_value);
539
579
}
@@ -543,14 +583,11 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
543
583
* An include directive isn't a variable and should be processed
544
584
* immediately.
545
585
*/
546
- unsigned int save_ConfigFileLineno = ConfigFileLineno;
547
-
548
586
if (!ParseConfigFile (opt_value, config_file, true ,
549
587
depth + 1 , elevel,
550
588
head_p, tail_p))
551
589
OK = false ;
552
590
yy_switch_to_buffer (lex_buffer);
553
- ConfigFileLineno = save_ConfigFileLineno;
554
591
pfree (opt_name);
555
592
pfree (opt_value);
556
593
}
@@ -620,7 +657,11 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
620
657
break ;
621
658
}
622
659
660
+ cleanup:
623
661
yy_delete_buffer (lex_buffer);
662
+ /* Each recursion level must save and restore these static variables. */
663
+ ConfigFileLineno = save_ConfigFileLineno;
664
+ GUC_flex_fatal_jmp = save_GUC_flex_fatal_jmp;
624
665
return OK;
625
666
}
626
667
0 commit comments