1 /* Copyright comment */
10 static void yyerror(char *);
13 * Variables containing simple states.
16 static int struct_level = 0;
17 static char *do_str = NULL;
18 static int do_length = 0;
20 /* temporarily store record members while creating the data structure */
21 struct ECPGrecord_member *record_member_list[128] = { NULL };
24 * Handle the filename and line numbering.
26 char * input_filename = NULL;
32 fprintf(yyout, "\n#line %d \"%s\"\n", yylineno, input_filename);
36 * store the whenever action here
38 static struct when when_error, when_nf;
41 print_action(struct when *w)
45 case W_CONTINUE: fprintf(yyout, "continue;");
47 case W_BREAK: fprintf(yyout, "break;");
49 case W_SQLPRINT: fprintf(yyout, "sqlprint();");
51 case W_GOTO: fprintf(yyout, "goto %s;", w->str);
53 case W_DO: fprintf(yyout, "%s;", w->str);
55 case W_STOP: fprintf(yyout, "exit (1);");
57 default: fprintf(yyout, "{/* %d not implemented yet */}", w->code);
65 if (when_nf.code != W_NOTHING)
67 fprintf(yyout, "\nif (SQLCODE > 0) ");
68 print_action(&when_nf);
70 if (when_error.code != W_NOTHING)
72 fprintf(yyout, "\nif (SQLCODE < 0) ");
73 print_action(&when_error);
79 * Handling of the variables.
87 /* This is a linked list of the variable names and types. */
91 struct ECPGtype * type;
93 struct variable * next;
96 static struct variable * allvariables = NULL;
98 static struct variable *
99 find_variable(char * name)
103 for (p = allvariables; p; p = p->next)
105 if (strcmp(p->name, name) == 0)
110 char * errorstring = (char *) malloc(strlen(name) + 100);
112 sprintf(errorstring, "The variable :%s is not declared.", name);
114 yyerror(errorstring);
121 new_variable(const char * name, struct ECPGtype * type)
123 struct variable * p = (struct variable*) malloc(sizeof(struct variable));
125 p->name = strdup(name);
127 p->brace_level = braces_open;
129 p->next = allvariables;
134 remove_variables(int brace_level)
136 struct variable * p, *prev;
138 for (p = prev = allvariables; p; p = p ? p->next : NULL)
140 if (p->brace_level >= brace_level)
143 if (p == allvariables)
144 prev = allvariables = p->next;
146 prev->next = p->next;
148 ECPGfree_type(p->type);
160 * Here are the variables that need to be handled on every request.
161 * These are of two kinds: input and output.
162 * I will make two lists for them.
165 struct variable * variable;
166 struct arguments * next;
170 static struct arguments * argsinsert = NULL;
171 static struct arguments * argsresult = NULL;
174 reset_variables(void)
181 /* Add a variable to a request. */
183 add_variable(struct arguments ** list, struct variable * var)
185 struct arguments * p = (struct arguments *)malloc(sizeof(struct arguments));
192 /* Dump out a list of all the variable on this list.
193 This is a recursive function that works from the end of the list and
194 deletes the list as we go on.
197 dump_variables(struct arguments * list)
204 /* The list is build up from the beginning so lets first dump the
208 dump_variables(list->next);
210 /* Then the current element. */
211 ECPGdump_a_type(yyout, list->variable->name, list->variable->type, NULL);
213 /* Then release the list element. */
220 struct ECPGtemp_type type;
223 enum ECPGttype type_enum;
227 %token <tagname> SQL_START SQL_SEMI SQL_STRING SQL_INTO
228 %token <tagname> SQL_BEGIN SQL_END SQL_DECLARE SQL_SECTION SQL_INCLUDE
229 %token <tagname> SQL_CONNECT SQL_OPEN SQL_EXECUTE SQL_IMMEDIATE
230 %token <tagname> SQL_COMMIT SQL_ROLLBACK SQL_RELEASE SQL_WORK SQL_WHENEVER
231 %token <tagname> SQL_SQLERROR SQL_NOT_FOUND SQL_CONTINUE
232 %token <tagname> SQL_DO SQL_GOTO SQL_SQLPRINT SQL_STOP
234 %token <tagname> S_SYMBOL S_LENGTH S_ANYTHING S_LABEL
235 %token <tagname> S_VARCHAR S_VARCHAR2
236 %token <tagname> S_EXTERN S_STATIC S_AUTO S_CONST S_REGISTER S_STRUCT
237 %token <tagname> S_UNSIGNED S_SIGNED
238 %token <tagname> S_LONG S_SHORT S_INT S_CHAR S_FLOAT S_DOUBLE S_BOOL
239 %token <tagname> '[' ']' ';' ',' '{' '}' '=' '*' '(' ')'
241 %type <type> type type_detailed varchar_type simple_type struct_type string_type
242 /* % type <type> array_type pointer_type */
243 %type <symbolname> symbol label
244 %type <tagname> maybe_storage_clause varchar_tag db_name
245 %type <type_enum> simple_tag char_tag
246 %type <indexsize> index length
247 %type <action> action
248 %type <tagname> canything sqlanything both_anything vartext commit_release
253 statements : /* empty */
254 | statements statement;
256 statement : sqldeclaration
269 sqldeclaration : sql_startdeclare
270 variable_declarations
273 sql_startdeclare : SQL_START SQL_BEGIN SQL_DECLARE SQL_SECTION SQL_SEMI {
274 fprintf(yyout, "/* exec sql begin declare section */\n");
275 output_line_number();
278 sql_enddeclare : SQL_START SQL_END SQL_DECLARE SQL_SECTION SQL_SEMI {
279 fprintf(yyout,"/* exec sql end declare section */\n");
280 output_line_number();
283 variable_declarations : /* empty */
284 | variable_declarations variable_declaration;
286 /* Here is where we can enter support for typedef. */
287 variable_declaration : type initializer ';' {
288 /* don't worry about our list when we're working on a struct */
289 if (struct_level == 0)
291 new_variable($<type>1.name, $<type>1.typ);
292 free((void *)$<type>1.name);
297 initializer : /*empty */
298 | '=' {fwrite(yytext, yyleng, 1, yyout);} vartext;
300 vartext : /* empty */ {}
301 | vartext both_anything {
303 fwrite(yytext, yyleng, 1, yyout);
306 if (strlen(do_str) + yyleng + 1 >= do_length)
307 do_str = mm_realloc(do_str, do_length += yyleng);
309 strcat(do_str, yytext);
314 char * name = (char *)malloc(yyleng + 1);
316 strncpy(name, yytext, yyleng);
319 $<symbolname>$ = name;
322 type : maybe_storage_clause type_detailed { $<type>$ = $<type>2; };
323 type_detailed : varchar_type { $<type>$ = $<type>1; }
324 | simple_type { $<type>$ = $<type>1; }
325 | string_type { $<type>$ = $<type>1; }
326 /* | array_type {$<type>$ = $<type>1; }
327 | pointer_type {$<type>$ = $<type>1; }*/
328 | struct_type {$<type>$ = $<type>1; };
330 varchar_type : varchar_tag symbol index {
331 if ($<indexsize>3 > 0L)
332 fprintf(yyout, "struct varchar_%s { int len; char arr[%ld]; } %s", $<symbolname>2, $<indexsize>3, $<symbolname>2);
334 fprintf(yyout, "struct varchar_%s { int len; char arr[]; } %s", $<symbolname>2, $<symbolname>2);
335 if (struct_level == 0)
337 $<type>$.name = $<symbolname>2;
338 $<type>$.typ = ECPGmake_varchar_type(ECPGt_varchar, $<indexsize>3);
341 ECPGmake_record_member($<symbolname>2, ECPGmake_varchar_type(ECPGt_varchar, $<indexsize>3), &(record_member_list[struct_level-1]));
344 varchar_tag : S_VARCHAR { $<tagname>$ = $<tagname>1; }
345 | S_VARCHAR2 { $<tagname>$ = $<tagname>1; };
347 simple_type : simple_tag symbol {
348 fprintf(yyout, "%s %s", ECPGtype_name($<type_enum>1), $<symbolname>2);
349 if (struct_level == 0)
351 $<type>$.name = $<symbolname>2;
352 $<type>$.typ = ECPGmake_simple_type($<type_enum>1, 1);
355 ECPGmake_record_member($<symbolname>2, ECPGmake_simple_type($<type_enum>1, 1), &(record_member_list[struct_level-1]));
358 string_type : char_tag symbol index {
359 if ($<indexsize>3 > 0L)
360 fprintf(yyout, "%s %s [%ld]", ECPGtype_name($<type_enum>1), $<symbolname>2, $<indexsize>3);
362 fprintf(yyout, "%s %s []", ECPGtype_name($<type_enum>1), $<symbolname>2);
363 if (struct_level == 0)
365 $<type>$.name = $<symbolname>2;
366 $<type>$.typ = ECPGmake_simple_type($<type_enum>1, $<indexsize>3);
369 ECPGmake_record_member($<symbolname>2, ECPGmake_simple_type($<type_enum>1, $<indexsize>3), &(record_member_list[struct_level-1]));
371 | char_tag '*' symbol {
372 fprintf(yyout, "%s *%s", ECPGtype_name($<type_enum>1), $<symbolname>3);
373 if (struct_level == 0)
375 $<type>$.name = $<symbolname>3;
376 $<type>$.typ = ECPGmake_simple_type($<type_enum>1, 0);
379 ECPGmake_record_member($<symbolname>3, ECPGmake_simple_type($<type_enum>1, 0), &(record_member_list[struct_level-1]));
382 fprintf(yyout, "%s %s", ECPGtype_name($<type_enum>1), $<symbolname>2);
383 if (struct_level == 0)
385 $<type>$.name = $<symbolname>2;
386 $<type>$.typ = ECPGmake_simple_type($<type_enum>1, 1);
389 ECPGmake_record_member($<symbolname>2, ECPGmake_simple_type($<type_enum>1, 1), &(record_member_list[struct_level-1]));
392 char_tag : S_CHAR { $<type_enum>$ = ECPGt_char; }
393 | S_UNSIGNED S_CHAR { $<type_enum>$ = ECPGt_unsigned_char; }
396 array_type : simple_tag symbol index {
397 if ($<indexsize>3 > 0)
398 fprintf(yyout, "%s %s [%ld]", ECPGtype_name($<type_enum>1), $<symbolname>2, $<indexsize>3);
400 fprintf(yyout, "%s %s []", ECPGtype_name($<type_enum>1), $<symbolname>2);
401 if (struct_level == 0)
403 $<type>$.name = $<symbolname>2;
404 $<type>$.typ = ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), $<indexsize>3);
407 ECPGmake_record_member($<symbolname>2, ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), $<indexsize>3), &(record_member_list[struct_level-1]));
410 pointer_type : simple_tag '*' symbol {
411 fprintf(yyout, "%s * %s", ECPGtype_name($<type_enum>1), $<symbolname>3);
412 if (struct_level == 0)
414 $<type>$.name = $<symbolname>3;
415 $<type>$.typ = ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), 0);
418 ECPGmake_record_member($<symbolname>3, ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), 0), &(record_member_list[struct_level-1]));
422 s_struct : S_STRUCT symbol {
424 fprintf(yyout, "struct %s {", $<symbolname>2);
427 struct_type : s_struct '{' variable_declarations '}' symbol {
429 if (struct_level == 0)
431 $<type>$.name = $<symbolname>5;
432 $<type>$.typ = ECPGmake_record_type(record_member_list[struct_level]);
435 ECPGmake_record_member($<symbolname>5, ECPGmake_record_type(record_member_list[struct_level]), &(record_member_list[struct_level-1]));
436 fprintf(yyout, "} %s", $<symbolname>5);
437 record_member_list[struct_level] = NULL;
440 simple_tag : S_SHORT { $<type_enum>$ = ECPGt_short; }
441 | S_UNSIGNED S_SHORT { $<type_enum>$ = ECPGt_unsigned_short; }
442 | S_INT { $<type_enum>$ = ECPGt_int; }
443 | S_UNSIGNED S_INT { $<type_enum>$ = ECPGt_unsigned_int; }
444 | S_LONG { $<type_enum>$ = ECPGt_long; }
445 | S_UNSIGNED S_LONG { $<type_enum>$ = ECPGt_unsigned_long; }
446 | S_FLOAT { $<type_enum>$ = ECPGt_float; }
447 | S_DOUBLE { $<type_enum>$ = ECPGt_double; }
448 | S_BOOL { $<type_enum>$ = ECPGt_bool; };
450 maybe_storage_clause : S_EXTERN { fwrite(yytext, yyleng, 1, yyout); }
451 | S_STATIC { fwrite(yytext, yyleng, 1, yyout); }
452 | S_SIGNED { fwrite(yytext, yyleng, 1, yyout); }
453 | S_CONST { fwrite(yytext, yyleng, 1, yyout); }
454 | S_REGISTER { fwrite(yytext, yyleng, 1, yyout); }
455 | S_AUTO { fwrite(yytext, yyleng, 1, yyout); }
458 index : '[' length ']' { $<indexsize>$ = $<indexsize>2; }
459 | '[' ']' { $<indexsize>$ = 0L; }
461 length : S_LENGTH { $<indexsize>$ = atol(yytext); }
463 sqlinclude : SQL_START SQL_INCLUDE { fprintf(yyout, "#include \""); }
464 filename SQL_SEMI { fprintf(yyout, ".h\""); output_line_number(); };
469 sqlconnect : SQL_START SQL_CONNECT { fprintf(yyout, "ECPGconnect("); }
471 SQL_SEMI { fprintf(yyout, ");"); whenever_action();}
473 db_name : SQL_STRING { fprintf(yyout, "\""); fwrite(yytext + 1, yyleng - 2, 1, yyout); fprintf(yyout, "\""); }
474 | ':' symbol { /* check if we have a char variable */
475 struct variable *p = find_variable($<symbolname>2);
476 enum ECPGttype typ = p->type->typ;
478 /* if array see what's inside */
479 if (typ == ECPGt_array)
480 typ = p->type->u.element->typ;
482 if (typ != ECPGt_char && typ != ECPGt_unsigned_char)
483 yyerror("invalid datatype");
485 fprintf(yyout, "%s", $<symbolname>2);
488 /* Open is an open cursor. Removed. */
489 sqlopen : SQL_START SQL_OPEN sqlgarbage SQL_SEMI { output_line_number(); };
491 sqlgarbage : /* Empty */
492 | sqlgarbage sqlanything;
495 sqlcommit : SQL_START commit_release SQL_SEMI {
496 fprintf(yyout, "ECPGcommit(__LINE__);");
500 commit_release : SQL_COMMIT
501 | SQL_COMMIT SQL_RELEASE
502 | SQL_COMMIT SQL_WORK SQL_RELEASE;
504 sqlrollback : SQL_START SQL_ROLLBACK SQL_SEMI {
505 fprintf(yyout, "ECPGrollback(__LINE__);");
509 sqlexecute : SQL_START SQL_EXECUTE SQL_IMMEDIATE ':' symbol SQL_SEMI {
510 fprintf(yyout, "ECPGdo(__LINE__, %s, ECPGt_EOIT, ECPGt_EORT );", $5);
514 sqlwhenever : SQL_START SQL_WHENEVER SQL_SQLERROR {
515 fprintf(yyout, "/* exec sql whenever sqlerror ");
517 when_error.code = $<action>5.code;
518 when_error.str = $<action>5.str;
519 fprintf(yyout, "; */\n");
521 | SQL_START SQL_WHENEVER SQL_NOT_FOUND {
522 fprintf(yyout, "/* exec sql whenever not found ");
524 when_nf.code = $<action>5.code;
525 when_nf.str=$<action>5.str;
526 fprintf(yyout, "; */\n");
529 action : SQL_CONTINUE {
530 $<action>$.code = W_NOTHING;
531 $<action>$.str = NULL;
532 fprintf(yyout, "continue");
535 $<action>$.code = W_SQLPRINT;
536 $<action>$.str = NULL;
537 fprintf(yyout, "sqlprint");
540 $<action>$.code = W_STOP;
541 $<action>$.str = NULL;
542 fprintf(yyout, "stop");
545 $<action>$.code = W_GOTO;
546 $<action>$.str = $<symbolname>2;
547 fprintf(yyout, "goto %s", $<symbolname>2);
550 $<action>$.code = W_GOTO;
551 $<action>$.str = $<symbolname>2;
552 fprintf(yyout, "goto %s", $<symbolname>2);
554 | SQL_DO symbol '(' {
555 do_str = (char *) mm_alloc(do_length = strlen($<symbolname>2) + 4);
556 sprintf(do_str, "%s (", $<symbolname>2);
558 do_str[strlen(do_str)+1]='\0';
559 do_str[strlen(do_str)]=')';
560 $<action>$.code = W_DO;
561 $<action>$.str = do_str;
562 fprintf(yyout, "do %s", do_str);
568 char * name = (char *)malloc(yyleng + 1);
570 strncpy(name, yytext, yyleng);
573 $<symbolname>$ = name;
576 sqlstatement : SQL_START { /* Reset stack */
578 fprintf(yyout, "ECPGdo(__LINE__, \"");
579 } sqlstatement_words SQL_SEMI {
581 fprintf(yyout, "\", ");
582 dump_variables(argsinsert);
583 fprintf(yyout, "ECPGt_EOIT, ");
584 dump_variables(argsresult);
585 fprintf(yyout, "ECPGt_EORT );");
589 sqlstatement_words : sqlstatement_word
590 | sqlstatement_words sqlstatement_word;
592 sqlstatement_word : ':' symbol
594 add_variable(&argsinsert, find_variable($2));
595 fprintf(yyout, " ;; ");
597 | SQL_INTO into_list { }
600 fwrite(yytext, yyleng, 1, yyout);
601 fwrite(" ", 1, 1, yyout);
603 | SQL_INTO sqlanything
605 fprintf(yyout, " into ");
606 fwrite(yytext, yyleng, 1, yyout);
607 fwrite(" ", 1, 1, yyout);
610 into_list : ':' symbol {
611 add_variable(&argsresult, find_variable($2));
613 | into_list ',' ':' symbol {
614 add_variable(&argsresult, find_variable($4));
618 fwrite(yytext, yyleng, 1, yyout);
621 canything : both_anything
625 sqlanything : both_anything;
627 both_anything : S_LENGTH | S_VARCHAR | S_VARCHAR2
628 | S_LONG | S_SHORT | S_INT | S_CHAR | S_FLOAT | S_DOUBLE | S_BOOL
629 | SQL_OPEN | SQL_CONNECT
631 | SQL_BEGIN | SQL_END
632 | SQL_DECLARE | SQL_SECTION
635 | S_STATIC | S_EXTERN | S_AUTO | S_CONST | S_REGISTER | S_STRUCT
636 | '[' | ']' | ',' | '=' | '*' | '(' | ')'
641 fwrite(yytext, yyleng, 1, yyout);
645 remove_variables(braces_open--);
646 fwrite(yytext, yyleng, 1, yyout);
650 static void yyerror(char * error)
652 fprintf(stderr, "%s in line %d\n", error, yylineno);