diff options
Diffstat (limited to 'src/interfaces/ecpg/preproc/parse.pl')
-rw-r--r-- | src/interfaces/ecpg/preproc/parse.pl | 374 |
1 files changed, 200 insertions, 174 deletions
diff --git a/src/interfaces/ecpg/preproc/parse.pl b/src/interfaces/ecpg/preproc/parse.pl index 0e7bc5eecc0..c772b2ac95a 100644 --- a/src/interfaces/ecpg/preproc/parse.pl +++ b/src/interfaces/ecpg/preproc/parse.pl @@ -7,7 +7,7 @@ # # Written by Mike Aubury <mike.aubury@aubit.com> # Michael Meskes <meskes@postgresql.org> -# Andy Colson <andy@squeakycode.net> +# Andy Colson <andy@squeakycode.net> # # Placed under the same license as PostgreSQL. # @@ -26,9 +26,9 @@ my $header_included = 0; my $feature_not_supported = 0; my $tokenmode = 0; -my(%buff, $infield, $comment, %tokens, %addons ); -my($stmt_mode, @fields); -my($line, $non_term_id); +my (%buff, $infield, $comment, %tokens, %addons); +my ($stmt_mode, @fields); +my ($line, $non_term_id); # some token have to be replaced by other symbols @@ -38,8 +38,7 @@ my %replace_token = ( 'FCONST' => 'ecpg_fconst', 'Sconst' => 'ecpg_sconst', 'IDENT' => 'ecpg_ident', - 'PARAM' => 'ecpg_param', -); + 'PARAM' => 'ecpg_param',); # or in the block my %replace_string = ( @@ -48,8 +47,7 @@ my %replace_string = ( 'NULLS_LAST' => 'nulls last', 'TYPECAST' => '::', 'DOT_DOT' => '..', - 'COLON_EQUALS' => ':=', -); + 'COLON_EQUALS' => ':=',); # specific replace_types for specific non-terminals - never include the ':' # ECPG-only replace_types are defined in ecpg-replace_types @@ -65,8 +63,7 @@ my %replace_types = ( 'ColId' => 'ignore', 'type_function_name' => 'ignore', 'ColLabel' => 'ignore', - 'Sconst' => 'ignore', -); + 'Sconst' => 'ignore',); # these replace_line commands excise certain keywords from the core keyword # lists. Be sure to account for these in ColLabel and related productions. @@ -90,18 +87,21 @@ my %replace_line = ( 'fetch_argsFORWARDopt_from_incursor_name' => 'ignore', 'fetch_argsBACKWARDopt_from_incursor_name' => 'ignore', "opt_array_boundsopt_array_bounds'['Iconst']'" => 'ignore', - 'VariableShowStmtSHOWvar_name' => 'SHOW var_name ecpg_into', + 'VariableShowStmtSHOWvar_name' => 'SHOW var_name ecpg_into', 'VariableShowStmtSHOWTIMEZONE' => 'SHOW TIME ZONE ecpg_into', - 'VariableShowStmtSHOWTRANSACTIONISOLATIONLEVEL' => 'SHOW TRANSACTION ISOLATION LEVEL ecpg_into', - 'VariableShowStmtSHOWSESSIONAUTHORIZATION' => 'SHOW SESSION AUTHORIZATION ecpg_into', - 'returning_clauseRETURNINGtarget_list' => 'RETURNING target_list ecpg_into', - 'ExecuteStmtEXECUTEnameexecute_param_clause' => 'EXECUTE prepared_name execute_param_clause execute_rest', - 'ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEnameexecute_param_clause' => - 'CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause', - 'PrepareStmtPREPAREnameprep_type_clauseASPreparableStmt' => - 'PREPARE prepared_name prep_type_clause AS PreparableStmt', - 'var_nameColId' => 'ECPGColId', -); + 'VariableShowStmtSHOWTRANSACTIONISOLATIONLEVEL' => + 'SHOW TRANSACTION ISOLATION LEVEL ecpg_into', + 'VariableShowStmtSHOWSESSIONAUTHORIZATION' => + 'SHOW SESSION AUTHORIZATION ecpg_into', + 'returning_clauseRETURNINGtarget_list' => + 'RETURNING target_list ecpg_into', + 'ExecuteStmtEXECUTEnameexecute_param_clause' => + 'EXECUTE prepared_name execute_param_clause execute_rest', +'ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEnameexecute_param_clause' + => 'CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause', + 'PrepareStmtPREPAREnameprep_type_clauseASPreparableStmt' => + 'PREPARE prepared_name prep_type_clause AS PreparableStmt', + 'var_nameColId' => 'ECPGColId',); preload_addons(); @@ -112,44 +112,45 @@ dump_buffer('tokens'); dump_buffer('types'); dump_buffer('ecpgtype'); dump_buffer('orig_tokens'); -print '%%', "\n"; +print '%%', "\n"; print 'prog: statements;', "\n"; dump_buffer('rules'); -include_file( 'trailer', 'ecpg.trailer' ); +include_file('trailer', 'ecpg.trailer'); dump_buffer('trailer'); sub main { - line: while (<>) + line: while (<>) { - if (/ERRCODE_FEATURE_NOT_SUPPORTED/) + if (/ERRCODE_FEATURE_NOT_SUPPORTED/) { $feature_not_supported = 1; next line; } - chomp; - - # comment out the line below to make the result file match (blank line wise) - # the prior version. - #next if ($_ eq ''); - - # Dump the action for a rule - - # stmt_mode indicates if we are processing the 'stmt:' - # rule (mode==0 means normal, mode==1 means stmt:) - # flds are the fields to use. These may start with a '$' - in - # which case they are the result of a previous non-terminal - # - # if they dont start with a '$' then they are token name - # - # len is the number of fields in flds... - # leadin is the padding to apply at the beginning (just use for formatting) - - if (/^%%/) { + chomp; + + # comment out the line below to make the result file match (blank line wise) + # the prior version. + #next if ($_ eq ''); + + # Dump the action for a rule - + # stmt_mode indicates if we are processing the 'stmt:' + # rule (mode==0 means normal, mode==1 means stmt:) + # flds are the fields to use. These may start with a '$' - in + # which case they are the result of a previous non-terminal + # + # if they dont start with a '$' then they are token name + # + # len is the number of fields in flds... + # leadin is the padding to apply at the beginning (just use for formatting) + + if (/^%%/) + { $tokenmode = 2; $copymode = 1; $yaccmode++; - $infield = 0; + $infield = 0; } my $prec = 0; @@ -165,130 +166,136 @@ sub main # Now split the line into individual fields my @arr = split(' '); - if ( $arr[0] eq '%token' && $tokenmode == 0 ) + if ($arr[0] eq '%token' && $tokenmode == 0) { $tokenmode = 1; - include_file( 'tokens', 'ecpg.tokens' ); + include_file('tokens', 'ecpg.tokens'); } - elsif ( $arr[0] eq '%type' && $header_included == 0 ) + elsif ($arr[0] eq '%type' && $header_included == 0) { - include_file( 'header', 'ecpg.header' ); - include_file( 'ecpgtype', 'ecpg.type' ); + include_file('header', 'ecpg.header'); + include_file('ecpgtype', 'ecpg.type'); $header_included = 1; } - if ( $tokenmode == 1 ) + if ($tokenmode == 1) { - my $str = ''; + my $str = ''; my $prior = ''; for my $a (@arr) { - if ( $a eq '/*' ) + if ($a eq '/*') { $comment++; next; } - if ( $a eq '*/' ) + if ($a eq '*/') { $comment--; next; } - if ($comment) + if ($comment) { next; } - if ( substr( $a, 0, 1 ) eq '<' ) { + if (substr($a, 0, 1) eq '<') + { next; # its a type } - $tokens{ $a } = 1; + $tokens{$a} = 1; $str = $str . ' ' . $a; - if ( $a eq 'IDENT' && $prior eq '%nonassoc' ) + if ($a eq 'IDENT' && $prior eq '%nonassoc') { + # add two more tokens to the list $str = $str . "\n%nonassoc CSTRING\n%nonassoc UIDENT"; } $prior = $a; } - add_to_buffer( 'orig_tokens', $str ); + add_to_buffer('orig_tokens', $str); next line; } - # Dont worry about anything if we're not in the right section of gram.y - if ( $yaccmode != 1 ) + # Dont worry about anything if we're not in the right section of gram.y + if ($yaccmode != 1) { next line; } - + # Go through each field in turn - for (my $fieldIndexer = 0 ; $fieldIndexer < scalar(@arr) ; $fieldIndexer++ ) + for ( + my $fieldIndexer = 0; + $fieldIndexer < scalar(@arr); + $fieldIndexer++) { - if ( $arr[$fieldIndexer] eq '*/' && $comment ) + if ($arr[$fieldIndexer] eq '*/' && $comment) { $comment = 0; next; } - elsif ($comment) + elsif ($comment) { next; } - elsif ( $arr[$fieldIndexer] eq '/*' ) + elsif ($arr[$fieldIndexer] eq '/*') { + # start of a multiline comment $comment = 1; next; } - elsif ( $arr[$fieldIndexer] eq '//' ) + elsif ($arr[$fieldIndexer] eq '//') { next line; } - elsif ( $arr[$fieldIndexer] eq '}' ) + elsif ($arr[$fieldIndexer] eq '}') { $brace_indent--; next; } - elsif ( $arr[$fieldIndexer] eq '{' ) + elsif ($arr[$fieldIndexer] eq '{') { $brace_indent++; next; } - if ( $brace_indent > 0 ) + if ($brace_indent > 0) { next; } - if ( $arr[$fieldIndexer] eq ';' ) + if ($arr[$fieldIndexer] eq ';') { - if ($copymode) + if ($copymode) { - if ( $infield ) + if ($infield) { - dump_line( $stmt_mode, \@fields ); + dump_line($stmt_mode, \@fields); } - add_to_buffer( 'rules', ";\n\n" ); + add_to_buffer('rules', ";\n\n"); } - else + else { $copymode = 1; } - @fields = (); - $infield = 0; - $line = ''; + @fields = (); + $infield = 0; + $line = ''; next; } - if ( $arr[$fieldIndexer] eq '|' ) + if ($arr[$fieldIndexer] eq '|') { - if ($copymode) + if ($copymode) { - if ( $infield ) + if ($infield) { - $infield = $infield + dump_line( $stmt_mode, \@fields ); + $infield = $infield + dump_line($stmt_mode, \@fields); } - if ( $infield > 1 ) + if ($infield > 1) { $line = '| '; } @@ -297,24 +304,24 @@ sub main next; } - if ( exists $replace_token{ $arr[$fieldIndexer] } ) + if (exists $replace_token{ $arr[$fieldIndexer] }) { $arr[$fieldIndexer] = $replace_token{ $arr[$fieldIndexer] }; } # Are we looking at a declaration of a non-terminal ? - if ( ( $arr[$fieldIndexer] =~ /[A-Za-z0-9]+:/ ) - || $arr[ $fieldIndexer + 1 ] eq ':' ) + if (($arr[$fieldIndexer] =~ /[A-Za-z0-9]+:/) + || $arr[ $fieldIndexer + 1 ] eq ':') { $non_term_id = $arr[$fieldIndexer]; $non_term_id =~ tr/://d; - if ( not defined $replace_types{$non_term_id} ) + if (not defined $replace_types{$non_term_id}) { $replace_types{$non_term_id} = '<str>'; $copymode = 1; } - elsif ( $replace_types{$non_term_id} eq 'ignore' ) + elsif ($replace_types{$non_term_id} eq 'ignore') { $copymode = 0; $line = ''; @@ -324,38 +331,43 @@ sub main # Do we have the : attached already ? # If yes, we'll have already printed the ':' - if ( !( $arr[$fieldIndexer] =~ '[A-Za-z0-9]+:' ) ) + if (!($arr[$fieldIndexer] =~ '[A-Za-z0-9]+:')) { + # Consume the ':' which is next... $line = $line . ':'; $fieldIndexer++; } # Special mode? - if ( $non_term_id eq 'stmt' ) + if ($non_term_id eq 'stmt') { $stmt_mode = 1; } - else + else { $stmt_mode = 0; } - my $tstr = '%type ' . $replace_types{$non_term_id} . ' ' . $non_term_id; - add_to_buffer( 'types', $tstr ); + my $tstr = + '%type ' + . $replace_types{$non_term_id} . ' ' + . $non_term_id; + add_to_buffer('types', $tstr); - if ($copymode) + if ($copymode) { - add_to_buffer( 'rules', $line ); + add_to_buffer('rules', $line); } - $line = ''; - @fields = (); - $infield = 1; + $line = ''; + @fields = (); + $infield = 1; next; } - elsif ($copymode) { + elsif ($copymode) + { $line = $line . ' ' . $arr[$fieldIndexer]; } - if ( $arr[$fieldIndexer] eq '%prec' ) + if ($arr[$fieldIndexer] eq '%prec') { $prec = 1; next; @@ -364,38 +376,37 @@ sub main if ( $copymode && !$prec && !$comment - && length( $arr[$fieldIndexer] ) - && $infield ) + && length($arr[$fieldIndexer]) + && $infield) { - if ( - $arr[$fieldIndexer] ne 'Op' - && ( $tokens{ $arr[$fieldIndexer] } > 0 || $arr[$fieldIndexer] =~ /'.+'/ ) - || $stmt_mode == 1 - ) + if ($arr[$fieldIndexer] ne 'Op' + && ( $tokens{ $arr[$fieldIndexer] } > 0 + || $arr[$fieldIndexer] =~ /'.+'/) + || $stmt_mode == 1) { my $S; - if ( exists $replace_string{ $arr[$fieldIndexer] } ) + if (exists $replace_string{ $arr[$fieldIndexer] }) { $S = $replace_string{ $arr[$fieldIndexer] }; } - else + else { $S = $arr[$fieldIndexer]; } $S =~ s/_P//g; $S =~ tr/'//d; - if ( $stmt_mode == 1 ) + if ($stmt_mode == 1) { push(@fields, $S); } - else + else { push(@fields, lc($S)); } } - else + else { - push(@fields, '$' . (scalar(@fields)+1)); + push(@fields, '$' . (scalar(@fields) + 1)); } } } @@ -405,43 +416,43 @@ sub main # append a file onto a buffer. # Arguments: buffer_name, filename (without path) -sub include_file +sub include_file { my ($buffer, $filename) = @_; my $full = "$path/$filename"; open(my $fh, '<', $full) or die; - while ( <$fh> ) + while (<$fh>) { chomp; - add_to_buffer( $buffer, $_ ); + add_to_buffer($buffer, $_); } close($fh); } sub include_addon { - my($buffer, $block, $fields, $stmt_mode) = @_; + my ($buffer, $block, $fields, $stmt_mode) = @_; my $rec = $addons{$block}; return 0 unless $rec; - - if ( $rec->{type} eq 'rule' ) + + if ($rec->{type} eq 'rule') { - dump_fields( $stmt_mode, $fields, ' { ' ); + dump_fields($stmt_mode, $fields, ' { '); } - elsif ( $rec->{type} eq 'addon' ) + elsif ($rec->{type} eq 'addon') { - add_to_buffer( 'rules', ' { ' ); + add_to_buffer('rules', ' { '); } #add_to_buffer( $stream, $_ ); - #We have an array to add to the buffer, we'll add it ourself instead of + #We have an array to add to the buffer, we'll add it ourself instead of #calling add_to_buffer, which does not know about arrays - - push( @{ $buff{$buffer} }, @{ $rec->{lines} } ); - if ( $rec->{type} eq 'addon' ) + push(@{ $buff{$buffer} }, @{ $rec->{lines} }); + + if ($rec->{type} eq 'addon') { - dump_fields( $stmt_mode, $fields, '' ); + dump_fields($stmt_mode, $fields, ''); } @@ -454,56 +465,60 @@ sub include_addon # include_addon does this same thing, but does not call this # sub... so if you change this, you need to fix include_addon too # Pass: buffer_name, string_to_append -sub add_to_buffer +sub add_to_buffer { - push( @{ $buff{$_[0]} }, "$_[1]\n" ); + push(@{ $buff{ $_[0] } }, "$_[1]\n"); } -sub dump_buffer +sub dump_buffer { - my($buffer) = @_; - print '/* ', $buffer, ' */',"\n"; + my ($buffer) = @_; + print '/* ', $buffer, ' */', "\n"; my $ref = $buff{$buffer}; print @$ref; } -sub dump_fields +sub dump_fields { - my ( $mode, $flds, $ln ) = @_; + my ($mode, $flds, $ln) = @_; my $len = scalar(@$flds); - if ( $mode == 0 ) + if ($mode == 0) { + #Normal - add_to_buffer( 'rules', $ln ); - if ( $feature_not_supported == 1 ) + add_to_buffer('rules', $ln); + if ($feature_not_supported == 1) { + # we found an unsupported feature, but we have to # filter out ExecuteStmt: CREATE OptTemp TABLE ... # because the warning there is only valid in some situations - if ( $flds->[0] ne 'create' || $flds->[2] ne 'table' ) + if ($flds->[0] ne 'create' || $flds->[2] ne 'table') { - add_to_buffer( 'rules', - 'mmerror(PARSE_ERROR, ET_WARNING, "unsupported feature will be passed to server");' + add_to_buffer('rules', +'mmerror(PARSE_ERROR, ET_WARNING, "unsupported feature will be passed to server");' ); } $feature_not_supported = 0; } - if ( $len == 0 ) + if ($len == 0) { + # We have no fields ? - add_to_buffer( 'rules', ' $$=EMPTY; }' ); - } - else + add_to_buffer('rules', ' $$=EMPTY; }'); + } + else { - # Go through each field and try to 'aggregate' the tokens + + # Go through each field and try to 'aggregate' the tokens # into a single 'mm_strdup' where possible my @flds_new; my $str; - for ( my $z = 0 ; $z < $len ; $z++ ) + for (my $z = 0; $z < $len; $z++) { - if ( substr( $flds->[$z], 0, 1 ) eq '$' ) + if (substr($flds->[$z], 0, 1) eq '$') { push(@flds_new, $flds->[$z]); next; @@ -511,12 +526,14 @@ sub dump_fields $str = $flds->[$z]; - while (1) + while (1) { - if ( $z >= $len - 1 || substr( $flds->[ $z + 1 ], 0, 1 ) eq '$' ) + if ($z >= $len - 1 + || substr($flds->[ $z + 1 ], 0, 1) eq '$') { + # We're at the end... - push(@flds_new, "mm_strdup(\"$str\")"); + push(@flds_new, "mm_strdup(\"$str\")"); last; } $z++; @@ -526,67 +543,73 @@ sub dump_fields # So - how many fields did we end up with ? $len = scalar(@flds_new); - if ( $len == 1 ) + if ($len == 1) { + # Straight assignement $str = ' $$ = ' . $flds_new[0] . ';'; - add_to_buffer( 'rules', $str ); + add_to_buffer('rules', $str); } - else + else { + # Need to concatenate the results to form # our final string - $str = ' $$ = cat_str(' . $len . ',' . join(',', @flds_new) . ');'; - add_to_buffer( 'rules', $str ); + $str = + ' $$ = cat_str(' . $len . ',' . join(',', @flds_new) . ');'; + add_to_buffer('rules', $str); } - add_to_buffer( 'rules', '}' ); + add_to_buffer('rules', '}'); } } else { + # we're in the stmt: rule if ($len) { + # or just the statement ... - add_to_buffer( 'rules', ' { output_statement($1, 0, ECPGst_normal); }' ); + add_to_buffer('rules', + ' { output_statement($1, 0, ECPGst_normal); }'); } else { - add_to_buffer( 'rules', ' { $$ = NULL; }' ); + add_to_buffer('rules', ' { $$ = NULL; }'); } } } -sub dump_line +sub dump_line { - my($stmt_mode, $fields) = @_; + my ($stmt_mode, $fields) = @_; my $block = $non_term_id . $line; $block =~ tr/ |//d; my $rep = $replace_line{$block}; if ($rep) { - if ($rep eq 'ignore' ) + if ($rep eq 'ignore') { return 0; } - if ( index( $line, '|' ) != -1 ) + if (index($line, '|') != -1) { $line = '| ' . $rep; } - else + else { $line = $rep; } $block = $non_term_id . $line; $block =~ tr/ |//d; } - add_to_buffer( 'rules', $line ); - my $i = include_addon( 'rules', $block, $fields, $stmt_mode); - if ( $i == 0 ) + add_to_buffer('rules', $line); + my $i = include_addon('rules', $block, $fields, $stmt_mode); + if ($i == 0) { - dump_fields( $stmt_mode, $fields, ' { ' ); + dump_fields($stmt_mode, $fields, ' { '); } return 1; } @@ -599,16 +622,19 @@ sub dump_line } =cut + sub preload_addons { my $filename = $path . "/ecpg.addons"; open(my $fh, '<', $filename) or die; - # there may be multple lines starting ECPG: and then multiple lines of code. - # the code need to be add to all prior ECPG records. + + # there may be multple lines starting ECPG: and then multiple lines of code. + # the code need to be add to all prior ECPG records. my (@needsRules, @code, $record); + # there may be comments before the first ECPG line, skip them my $skip = 1; - while ( <$fh> ) + while (<$fh>) { if (/^ECPG:\s(\S+)\s?(\w+)?/) { @@ -619,16 +645,16 @@ sub preload_addons { push(@{ $x->{lines} }, @code); } - @code = (); + @code = (); @needsRules = (); } - $record = {}; - $record->{type} = $2; + $record = {}; + $record->{type} = $2; $record->{lines} = []; if (exists $addons{$1}) { die "Ga! there are dups!\n"; } $addons{$1} = $record; push(@needsRules, $record); - } + } else { next if $skip; |