summaryrefslogtreecommitdiff
path: root/src/interfaces/ecpg/preproc/check_rules.pl
blob: 73f4486f859de2218c662874694fda3b08cecd96 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/perl
# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/check_rules.pl,v 1.1 2009/11/27 10:00:40 meskes Exp $
# test parser generater for ecpg
# call with backend parser as stdin
#
# Copyright (c) 2009, PostgreSQL Global Development Group
#
# Written by Michael Meskes <[email protected]>
#
# Placed under the same license as PostgreSQL.
#

if (@ARGV) {
        $path = $ARGV[0];
        $parser = $ARGV[1];
}

$[ = 1;                 # set array base to 1

if ($path eq '') { $path = "."; }
$filename = $path . "/ecpg.addons";

if ($parser eq '') { $parser = "../../../backend/parser/gram.y"; }

$replace_line{'ExecuteStmtEXECUTEnameexecute_param_clause'} = 'EXECUTE prepared_name execute_param_clause execute_rest';
$replace_line{'ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEnameexecute_param_clause'} = 'CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause';
$replace_line{'PrepareStmtPREPAREnameprep_type_clauseASPreparableStmt'} = 'PREPARE prepared_name prep_type_clause AS PreparableStmt';

$block = '';
$ret = 0;
$yaccmod = 0;
$brace_indent = 0;

open GRAM, $parser or die $!;
while (<GRAM>) {
	chomp;      # strip record separator

	if (/^%%/) {
        	$yaccmode++;
	}

	if ($yaccmode != 1) {
	        next;
    	}

	$S = $_;
	$prec = 0;

	# Make sure any braces are split
	$S =~ s/{/ { /g;
	$S =~ s/}/ } /g;
	# Any comments are split
	$S =~ s#[/][*]# /* #g;
	$S =~ s#[*][/]# */ #g;

	# Now split the line into individual fields
	$n = (@arr = split(' ', $S));

	# Go through each field in turn
	for ($fieldIndexer = 1; $fieldIndexer <= $n; $fieldIndexer++) {
		if ($arr[$fieldIndexer] eq '*/' && $comment) {
		    $comment = 0;
		    next;
		}
		elsif ($comment) {
		    next;
		}
		elsif ($arr[$fieldIndexer] eq '/*') {
		    # start of a multiline comment
		    $comment = 1;
		    next;
		}
		elsif ($arr[$fieldIndexer] eq '//') {
		    next;
		}
		elsif ($arr[$fieldIndexer] eq '}') {
		    $brace_indent--;
		    next;
		}
		elsif ($arr[$fieldIndexer] eq '{') {
		    $brace_indent++;
		    next;
		}

		if ($brace_indent > 0) {
		    next;
		}

		if ($arr[$fieldIndexer] eq ';' || $arr[$fieldIndexer] eq '|') {
			$block = $non_term_id . $block;
			if ($replace_line{$block}) {
				$block = &generate_block($replace_line{$block});
			}
			$found{$block} = 'found';
			$block = '';
		}
		elsif (($arr[$fieldIndexer] =~ '[A-Za-z0-9]+:') || $arr[$fieldIndexer + 1] eq ':') {
			$non_term_id = $arr[$fieldIndexer];
			$non_term_id =~ s/://g;
		}
		else  {
			$block = $block . $arr[$fieldIndexer];
		}
	}
} 

close GRAM;

open ECPG, $filename or die $!;

line: while (<ECPG>) {
    chomp;	# strip record separator
    @Fld = split(' ', $_, -1);

    if (!/^ECPG:/) {
	next line; 
    }

    if ($found{$Fld[2]} ne 'found') {
	printf $Fld[2] . " is not used for building parser!\n";
	$ret = 1;
    }
}

close ECPG;

exit $ret;

sub generate_block {
    local($line) = @_;
    $block = $non_term_id . $line;
    $block =~ s/ //g;
    $s = "\\|", $block =~ s/$s//g;
    return $block;
}