2020#include " utils/guc.h"
2121
2222
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+ */
2429#undef fprintf
25- #define fprintf (file, fmt, msg ) ereport(ERROR, (errmsg_internal( " %s " , msg)) )
30+ #define fprintf (file, fmt, msg )GUC_flex_fatal( msg)
2631
2732enum {
2833GUC_ID =1 ,
@@ -37,10 +42,13 @@ enum {
3742};
3843
3944static unsigned int ConfigFileLineno;
45+ static const char *GUC_flex_fatal_errmsg;
46+ static sigjmp_buf *GUC_flex_fatal_jmp;
4047
4148/* flex fails to supply a prototype for yylex, so provide one */
4249int GUC_yylex (void );
4350
51+ static int GUC_flex_fatal (const char *msg);
4452static char *GUC_scanstr (const char *s);
4553
4654%}
@@ -436,6 +444,22 @@ ParseConfigFile(const char *config_file, const char *calling_file, bool strict,
436444return OK;
437445}
438446
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+
439463/*
440464 * Read and parse a single configuration file. This function recurses
441465 * to handle "include" directives.
@@ -464,19 +488,38 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
464488 ConfigVariable **head_p, ConfigVariable **tail_p)
465489{
466490bool 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_bufflex_fatal_jmp;
494+ volatile YY_BUFFER_STATE lex_buffer =NULL ;
468495int errorcount;
469496int token;
470497
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+
471514/*
472515 * Parse
473516 */
474- lex_buffer =yy_create_buffer (fp, YY_BUF_SIZE);
475- yy_switch_to_buffer (lex_buffer);
476-
477517ConfigFileLineno =1 ;
478518errorcount =0 ;
479519
520+ lex_buffer =yy_create_buffer (fp, YY_BUF_SIZE);
521+ yy_switch_to_buffer (lex_buffer);
522+
480523/* This loop iterates once per logical line */
481524while ((token =yylex ()))
482525{
@@ -526,14 +569,11 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
526569 * An include_if_exists directive isn't a variable and should be
527570 * processed immediately.
528571 */
529- unsigned int save_ConfigFileLineno = ConfigFileLineno;
530-
531572if (!ParseConfigFile (opt_value, config_file,false ,
532573 depth +1 , elevel,
533574 head_p, tail_p))
534575OK =false ;
535576yy_switch_to_buffer (lex_buffer);
536- ConfigFileLineno = save_ConfigFileLineno;
537577pfree (opt_name);
538578pfree (opt_value);
539579}
@@ -543,14 +583,11 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
543583 * An include directive isn't a variable and should be processed
544584 * immediately.
545585 */
546- unsigned int save_ConfigFileLineno = ConfigFileLineno;
547-
548586if (!ParseConfigFile (opt_value, config_file,true ,
549587 depth +1 , elevel,
550588 head_p, tail_p))
551589OK =false ;
552590yy_switch_to_buffer (lex_buffer);
553- ConfigFileLineno = save_ConfigFileLineno;
554591pfree (opt_name);
555592pfree (opt_value);
556593}
@@ -620,7 +657,11 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
620657break ;
621658}
622659
660+ cleanup:
623661yy_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;
624665return OK;
625666}
626667