add tool to check extensions.conf files for problems with new expression parser ...
[asterisk/asterisk.git] / utils / check_expr.c
1 #include <stdio.h>
2 #include <stddef.h>
3 #include <string.h>
4 #include <stdlib.h>
5
6 int lineno = 1;
7 int expr_count = 0;
8 int expr_max_size = 0;
9 int expr_tot_size = 0;
10 int warn_count = 0;
11 int OK_count = 0;
12
13 int check_expr(char *buffer, char *error_report)
14 {
15         char *cp;
16         int oplen = 0;
17         int warn_found = 0;
18
19         error_report[0] = 0;
20         
21         for(cp=buffer;*cp;cp++)
22         {
23                 
24                 if( *cp == '|' 
25                         || *cp == '&'
26                         || *cp == '='
27                         || *cp == '>'
28                         || *cp == '<'
29                         || *cp == '+'
30                         || *cp == '-'
31                         || *cp == '*'
32                         || *cp == '/'
33                         || *cp == '%'
34                         || *cp == '?'
35                         || *cp == ':'
36                         /*      || *cp == '('
37                                 || *cp == ')' These are pretty hard to track, as they are in funcalls, etc. */
38                         || *cp == '"' )
39                 {
40                         if( *cp == '"' )
41                         {
42                                 /* skip to the other end */
43                                 cp++;
44                                 while( *cp && *cp != '"' )
45                                         cp++;
46                                 if( *cp == 0 )
47                                 {
48                                         fprintf(stderr,"Trouble? Unterminated double quote found at line %d\n",
49                                                         lineno);
50                                 }
51                         }
52                         else
53                         {
54                                 if( ((*cp == '>'||*cp == '<' ||*cp=='!') && *(cp+1) == '=' ) )
55                                 {
56                                         oplen = 2;
57                                 }
58                                 else
59                                 {
60                                         oplen = 1;
61                                 }
62                                 
63                                 if( (cp > buffer && *(cp-1) != ' ') || *(cp+oplen) != ' ' )
64                                 {
65                                         char tbuf[1000];
66                                         if( oplen == 1 )
67                                                 sprintf(tbuf,"WARNING: line %d,  '%c' operator not separated by spaces. This may lead to confusion. You may wish to use double quotes to quote the grouping it is in. Please check!\n",
68                                                                 lineno, *cp);
69                                         else
70                                                 sprintf(tbuf,"WARNING: line %d,  '%c%c' operator not separated by spaces. This may lead to confusion. You may wish to use double quotes to quote the grouping it is in. Please check!\n",
71                                                                 lineno, *cp, *(cp+1));
72                                         strcat(error_report,tbuf);
73
74                                         warn_count++;
75                                         warn_found++;
76                                 }
77                         }
78                 }
79         }
80         return warn_found;
81 }
82
83
84 void parse_file(char *fname)
85 {
86         FILE *f = fopen(fname,"r");
87         FILE *l = fopen("expr2_log","w");
88         int c1;
89         char last_char= 0;
90         char buffer[30000]; /* I sure hope no expr gets this big! */
91         
92         if( !f )
93         {
94                 fprintf(stderr,"Couldn't open %s for reading... need an extensions.conf file to parse!\n");
95                 exit(20);
96         }
97         if( !l )
98         {
99                 fprintf(stderr,"Couldn't open 'expr2_log' file for writing... please fix and re-run!\n");
100                 exit(21);
101         }
102         
103         lineno = 1;
104         
105         while( (c1 = fgetc(f)) != EOF )
106         {
107                 if( c1 == '\n' )
108                         lineno++;
109                 else if( c1 == '[' )
110                 {
111                         if( last_char == '$' )
112                         {
113                                 /* bingo, an expr */
114                                 int bracklev = 1;
115                                 int bufcount = 0;
116                                 int retval;
117                                 char error_report[30000];
118                                 
119                                 while( (c1 = fgetc(f)) != EOF )
120                                 {
121                                         if( c1 == '[' )
122                                                 bracklev++;
123                                         else if( c1 == ']' )
124                                                 bracklev--;
125                                         if( c1 == '\n' )
126                                         {
127                                                 fprintf(l, "ERROR-- A newline in an expression? Weird! ...at line %d\n", lineno);
128                                                 fclose(f);
129                                                 fclose(l);
130                                                 printf("--- ERROR --- A newline in the middle of an expression at line %d!\n", lineno);
131                                         }
132                                         
133                                         if( bracklev == 0 )
134                                                 break;
135                                         buffer[bufcount++] = c1;
136                                 }
137                                 if( c1 == EOF )
138                                 {
139                                         fprintf(l, "ERROR-- End of File Reached in the middle of an Expr at line %d\n", lineno);
140                                         fclose(f);
141                                         fclose(l);
142                                         printf("--- ERROR --- EOF reached in middle of an expression at line %d!\n", lineno);
143                                         exit(22);
144                                 }
145                                 
146                                 buffer[bufcount] = 0;
147                                 /* update stats */
148                                 expr_tot_size += bufcount;
149                                 expr_count++;
150                                 if( bufcount > expr_max_size )
151                                         expr_max_size = bufcount;
152                                 
153                                 retval = check_expr(buffer, error_report); /* check_expr should bump the warning counter */
154                                 if( retval != 0 )
155                                 {
156                                         /* print error report */
157                                         printf("Warning(s) at line %d, expression: $[%s]; see expr2_log file for details\n", 
158                                                    lineno, buffer);
159                                         fprintf(l, "%s", error_report);
160                                 }
161                                 else
162                                 {
163                                         printf("OK -- $[%s] at line %d\n", buffer, lineno);
164                                         OK_count++;
165                                 }
166                         }
167                 }
168                 last_char = c1;
169         }
170         printf("Summary:\n  Expressions detected: %d\n  Expressions OK:  %d\n  Total # Warnings:   %d\n  Longest Expr:   %d chars\n  Ave expr len:  %d chars\n",
171                    expr_count,
172                    OK_count,
173                    warn_count,
174                    expr_max_size,
175                    (expr_count) ? expr_tot_size/expr_count : 0);
176         
177         fclose(f);
178         fclose(l);
179 }
180
181
182 main(int argc,char **argv)
183 {
184         if( argc < 2 )
185         {
186                 printf("Hey-- give me a path to an extensions.conf file!\n");
187                 exit(19);
188         }
189         
190         parse_file(argv[1]);
191 }