mirror of
https://github.com/postgres/postgres.git
synced 2025-11-07 19:06:32 +03:00
Erk, the whole directory structure changed on us here...
This commit is contained in:
33
src/interfaces/ecpg/preproc/Makefile
Normal file
33
src/interfaces/ecpg/preproc/Makefile
Normal file
@@ -0,0 +1,33 @@
|
||||
# Generated automatically from Makefile.in by configure.
|
||||
SRCDIR= ../../..
|
||||
include $(SRCDIR)/Makefile.global
|
||||
|
||||
CC=gcc
|
||||
LEX=flex
|
||||
LEXLIB=-lfl
|
||||
YACC=/usr/bin/bison
|
||||
YFLAGS=-y -d
|
||||
|
||||
CFLAGS=-I../include -O2 -g -Wall
|
||||
|
||||
all:: ecpg
|
||||
|
||||
clean:
|
||||
rm -f *.o core a.out ecpg preproc.tab.h y.tab.c *~
|
||||
|
||||
install: all
|
||||
install -c -m 755 ecpg $(BINDIR)
|
||||
|
||||
uninstall:
|
||||
rm -f $(BINDIR)/ecpg
|
||||
|
||||
# Rule that really do something.
|
||||
ecpg: y.tab.o pgc.o type.o ecpg.o
|
||||
$(CC) -g -O2 -Wall -o ecpg y.tab.o pgc.o type.o ecpg.o -L../lib -lecpg $(LEXLIB)
|
||||
|
||||
y.tab.h y.tab.c: preproc.y
|
||||
$(YACC) $(YFLAGS) $<
|
||||
|
||||
y.tab.o : y.tab.h ../include/ecpgtype.h
|
||||
type.o : ../include/ecpgtype.h
|
||||
pgc.o : ../include/ecpgtype.h
|
||||
32
src/interfaces/ecpg/preproc/Makefile.in
Normal file
32
src/interfaces/ecpg/preproc/Makefile.in
Normal file
@@ -0,0 +1,32 @@
|
||||
SRCDIR= ../../..
|
||||
include $(SRCDIR)/Makefile.global
|
||||
|
||||
CC=@CC@
|
||||
LEX=@LEX@
|
||||
LEXLIB=@LEXLIB@
|
||||
YACC=@YACC@
|
||||
YFLAGS=@YFLAGS@
|
||||
|
||||
CFLAGS=-I../include -O2 -g -Wall
|
||||
|
||||
all:: ecpg
|
||||
|
||||
clean:
|
||||
rm -f *.o core a.out ecpg preproc.tab.h y.tab.c *~
|
||||
|
||||
install: all
|
||||
install -c -m 755 ecpg $(BINDIR)
|
||||
|
||||
uninstall:
|
||||
rm -f $(BINDIR)/ecpg
|
||||
|
||||
# Rule that really do something.
|
||||
ecpg: y.tab.o pgc.o type.o ecpg.o
|
||||
$(CC) -g -O2 -Wall -o ecpg y.tab.o pgc.o type.o ecpg.o -L../lib -lecpg $(LEXLIB)
|
||||
|
||||
y.tab.h y.tab.c: preproc.y
|
||||
$(YACC) $(YFLAGS) $<
|
||||
|
||||
y.tab.o : y.tab.h ../include/ecpgtype.h
|
||||
type.o : ../include/ecpgtype.h
|
||||
pgc.o : ../include/ecpgtype.h
|
||||
106
src/interfaces/ecpg/preproc/ecpg.c
Normal file
106
src/interfaces/ecpg/preproc/ecpg.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/* New main for ecpg, the PostgreSQL embedded SQL precompiler. */
|
||||
/* (C) Michael Meskes <meskes@debian.org> Feb 5th, 1998 */
|
||||
/* Placed under the same copyright as PostgresSQL */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
|
||||
extern void lex_init(void);
|
||||
extern FILE *yyin, *yyout;
|
||||
extern char * input_filename;
|
||||
extern int yyparse(void);
|
||||
|
||||
static void
|
||||
usage(char *progname)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s: [ -o outout file name] file1 [file2] ...\n", progname);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *const argv[])
|
||||
{
|
||||
char c,
|
||||
out_option = 0;
|
||||
int fnr;
|
||||
|
||||
while ((c = getopt(argc, argv, "o:")) != EOF)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'o':
|
||||
yyout = fopen(optarg, "w");
|
||||
if (yyout == NULL)
|
||||
perror(optarg);
|
||||
else
|
||||
out_option = 1;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/* after the options there must not be anything but filenames */
|
||||
for (fnr = optind; fnr < argc; fnr++)
|
||||
{
|
||||
char *filename,
|
||||
*ptr2ext;
|
||||
|
||||
filename = malloc(strlen(argv[fnr]) + 2);
|
||||
if (filename == NULL)
|
||||
{
|
||||
perror("malloc");
|
||||
continue;
|
||||
}
|
||||
|
||||
strcpy(filename, argv[fnr]);
|
||||
|
||||
ptr2ext = strrchr(filename, '.');
|
||||
/* no extension or extension not equal .pgc */
|
||||
if (ptr2ext == NULL || strcmp(ptr2ext, ".pgc") != 0)
|
||||
{
|
||||
ptr2ext = filename + strlen(filename);
|
||||
ptr2ext[0] = '.';
|
||||
}
|
||||
|
||||
/* make extension = .c */
|
||||
ptr2ext[1] = 'c';
|
||||
ptr2ext[2] = '\0';
|
||||
|
||||
if (out_option == 0) /* calculate the output name */
|
||||
{
|
||||
yyout = fopen(filename, "w");
|
||||
if (yyout == NULL)
|
||||
{
|
||||
perror(filename);
|
||||
free(filename);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
yyin = fopen(input_filename = argv[fnr], "r");
|
||||
if (yyin == NULL)
|
||||
{
|
||||
perror(argv[fnr]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* initialize lex */
|
||||
lex_init();
|
||||
|
||||
/* we need two includes everytime */
|
||||
fprintf(yyout, "/* These two include files are added by the preprocessor */\n#include <ecpgtype.h>\n#include <ecpglib.h>\n");
|
||||
|
||||
/* and parse the source */
|
||||
yyparse();
|
||||
|
||||
fclose(yyin);
|
||||
if (out_option == 0)
|
||||
fclose(yyout);
|
||||
}
|
||||
|
||||
free(filename);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
116
src/interfaces/ecpg/preproc/pgc.l
Normal file
116
src/interfaces/ecpg/preproc/pgc.l
Normal file
@@ -0,0 +1,116 @@
|
||||
/* Copyright comment! */
|
||||
%{
|
||||
#include "type.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
extern int debugging;
|
||||
|
||||
#define dbg(arg) if (debugging) fprintf(stderr, "DEBUG, %d: %s\n", yylineno, #arg);
|
||||
%}
|
||||
%option yylineno
|
||||
%s C SQL
|
||||
ccomment \/\*([^*]|\*[^/]|\*\*[^/])*\*\/
|
||||
ws ([ \t\n][ \t\n]*|{ccomment})*
|
||||
letter [A-Za-z_]
|
||||
digit [0-9]
|
||||
length {digit}+
|
||||
symbol {letter}({letter}|{digit})*
|
||||
string '[^']*'
|
||||
|
||||
exec [eE][xX][eE][cC]
|
||||
sql [sS][qQ][lL]
|
||||
varchar [vV][aA][rR][cC][hH][aA][rR]
|
||||
varchar2 [vV][aA][rR][cC][hH][aA][rR]2
|
||||
into [iI][nN][tT][oO]
|
||||
begin [bB][eE][gG][iI][nN]
|
||||
end [eE][nN][dD]
|
||||
declare [dD][eE][cC][lL][aA][rR][eE]
|
||||
section [sS][eE][cC][tT][iI][oO][nN]
|
||||
include [iI][nN][cC][lL][uU][dD][eE]
|
||||
connect [cC][oO][nN][nN][eE][cC][tT]
|
||||
open [oO][pP][eE][nN]
|
||||
commit [cC][oO][mM][mM][iI][tT]
|
||||
rollback [rR][oO][lL][lL][bB][aA][cC][kK]
|
||||
%%
|
||||
<C>{exec}{ws}{sql} { BEGIN SQL; dbg(SQL_START); return SQL_START; }
|
||||
<SQL>";" { BEGIN C; dbg(SQL_SEMI); return SQL_SEMI; }
|
||||
<SQL>{begin} { dbg(SQL_BEGIN); return SQL_BEGIN; }
|
||||
<SQL>{end} { dbg(SQL_END); return SQL_END; }
|
||||
<SQL>{declare} { dbg(SQL_DECLARE); return SQL_DECLARE; }
|
||||
<SQL>{section} { dbg(SQL_SECTION); return SQL_SECTION; }
|
||||
<SQL>{include} { dbg(SQL_INCLUDE); return SQL_INCLUDE; }
|
||||
<SQL>{connect} { dbg(SQL_CONNECT); return SQL_CONNECT; }
|
||||
<SQL>{open} { dbg(SQL_OPEN); return SQL_OPEN; }
|
||||
<SQL>{commit} { dbg(SQL_COMMIT); return SQL_COMMIT; }
|
||||
<SQL>{rollback} { dbg(SQL_ROLLBACK); return SQL_ROLLBACK; }
|
||||
|
||||
<SQL>{into} { dbg(SQL_INTO); return SQL_INTO; }
|
||||
|
||||
{length} { dbg(S_LENGTH); return S_LENGTH; }
|
||||
|
||||
{varchar} { dbg(S_VARCHAR); return S_VARCHAR; }
|
||||
{varchar2} { dbg(S_VARCHAR2); return S_VARCHAR2; }
|
||||
long { dbg(S_LONG); return S_LONG; }
|
||||
short { dbg(S_SHORT); return S_SHORT; }
|
||||
int { dbg(S_INT); return S_INT; }
|
||||
char { dbg(S_CHAR); return S_CHAR; }
|
||||
float { dbg(S_FLOAT); return S_FLOAT; }
|
||||
double { dbg(S_DOUBLE); return S_DOUBLE; }
|
||||
bool { dbg(S_BOOL); return S_BOOL; }
|
||||
|
||||
{string} { dbg(SQL_STRING); return SQL_STRING; }
|
||||
<SQL>{ws} ;
|
||||
{symbol} { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
|
||||
<SQL>"!<" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"!>" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"!^" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"!|" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"!~" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"!~*" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"#<" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"#<=" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"#<>" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"#=" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"#>" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"#>=" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"&&" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"&<" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"&>" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"<<" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"<=" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"<===>" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"<>" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"<?>" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"===>" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"===`" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"=|=" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>">=" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>">>" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"@@" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"|/" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"||/" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"~*" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
<SQL>"~=" { dbg(S_SYMBOL); return S_SYMBOL; }
|
||||
|
||||
"[" { dbg([); return '['; }
|
||||
"]" { dbg(]); return ']'; }
|
||||
";" { dbg(;); return ';'; }
|
||||
"," { dbg(komma); return ','; }
|
||||
|
||||
<SQL>":" { dbg(:); return ':'; }
|
||||
|
||||
{ws} { ECHO; }
|
||||
. { dbg(.); return S_ANYTHING; }
|
||||
%%
|
||||
void
|
||||
lex_init(void)
|
||||
{
|
||||
BEGIN C;
|
||||
}
|
||||
|
||||
int yywrap(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
366
src/interfaces/ecpg/preproc/preproc.y
Normal file
366
src/interfaces/ecpg/preproc/preproc.y
Normal file
@@ -0,0 +1,366 @@
|
||||
/* Copyright comment */
|
||||
%{
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "type.h"
|
||||
|
||||
void yyerror(char *);
|
||||
extern FILE * yyout;
|
||||
extern char * yytext;
|
||||
extern int yylineno;
|
||||
extern int yyleng;
|
||||
|
||||
/*
|
||||
* Variables containing simple states.
|
||||
*/
|
||||
int debugging = 0;
|
||||
|
||||
/*
|
||||
* Handle the filename and line numbering.
|
||||
*/
|
||||
char * input_filename = NULL;
|
||||
|
||||
void
|
||||
output_line_number()
|
||||
{
|
||||
if (input_filename)
|
||||
fprintf(yyout, "\n#line %d \"%s\"\n", yylineno, input_filename);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handling of the variables.
|
||||
*/
|
||||
/* Since we don't want to keep track of where the functions end we just
|
||||
* have a list of functions that we search in, most reasently defined
|
||||
* function. This won't work if we use block scope for variables with the
|
||||
* same name but different types but in all other cases the c-compiler will
|
||||
* signal an error (hopefully).
|
||||
*
|
||||
* This list is leaked on program exit. This is because I don't think it is
|
||||
* important enough to spend the extra ten minutes to write the function that
|
||||
* deletes it. It would be another thing if I would have written in C++.
|
||||
*/
|
||||
/* This is a linked list of the variable names and types. */
|
||||
struct variable
|
||||
{
|
||||
char * name;
|
||||
struct ECPGtype * type;
|
||||
struct variable * next;
|
||||
};
|
||||
|
||||
static struct variable * allvariables = NULL;
|
||||
|
||||
struct variable *
|
||||
find_variable(char * name)
|
||||
{
|
||||
struct variable * p;
|
||||
|
||||
for (p = allvariables; p; p = p->next)
|
||||
{
|
||||
if (strcmp(p->name, name) == 0)
|
||||
return p;
|
||||
}
|
||||
|
||||
{
|
||||
char * errorstring = (char *) malloc(strlen(name) + 100);
|
||||
|
||||
sprintf(errorstring, "The variabel :%s is not declared.", name);
|
||||
|
||||
yyerror(errorstring);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
new_variable(const char * name, struct ECPGtype * type)
|
||||
{
|
||||
struct variable * p = (struct variable*) malloc(sizeof(struct variable));
|
||||
|
||||
p->name = strdup(name);
|
||||
p->type = type;
|
||||
|
||||
p->next = allvariables;
|
||||
allvariables = p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Here is the variables that need to be handled on every request.
|
||||
* These are of two kinds: input and output.
|
||||
* I will make two lists for them.
|
||||
*/
|
||||
struct arguments {
|
||||
struct variable * variable;
|
||||
struct arguments * next;
|
||||
};
|
||||
|
||||
|
||||
static struct arguments * argsinsert = NULL;
|
||||
static struct arguments * argsresult = NULL;
|
||||
|
||||
void
|
||||
reset_variables()
|
||||
{
|
||||
argsinsert = NULL;
|
||||
argsresult = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Add a variable to a request. */
|
||||
void
|
||||
add_variable(struct arguments ** list, struct variable * var)
|
||||
{
|
||||
struct arguments * p = (struct arguments *)malloc(sizeof(struct arguments));
|
||||
p->variable = var;
|
||||
p->next = *list;
|
||||
*list = p;
|
||||
}
|
||||
|
||||
|
||||
/* Dump out a list of all the variable on this list.
|
||||
This is a recursive function that works from the end of the list and
|
||||
deletes the list as we go on.
|
||||
*/
|
||||
void
|
||||
dump_variables(struct arguments * list)
|
||||
{
|
||||
if (list == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* The list is build up from the beginning so lets first dump the
|
||||
end of the list:
|
||||
*/
|
||||
|
||||
dump_variables(list->next);
|
||||
|
||||
/* Then the current element. */
|
||||
ECPGdump_a_type(yyout, list->variable->name, list->variable->type);
|
||||
|
||||
/* Then release the list element. */
|
||||
free(list);
|
||||
}
|
||||
%}
|
||||
|
||||
%union {
|
||||
int tagname;
|
||||
struct ECPGtemp_type type;
|
||||
char * symbolname;
|
||||
int indexsize;
|
||||
enum ECPGttype type_enum;
|
||||
}
|
||||
|
||||
%token <tagname> SQL_START SQL_SEMI SQL_STRING SQL_INTO
|
||||
%token <tagname> SQL_BEGIN SQL_END SQL_DECLARE SQL_SECTION SQL_INCLUDE
|
||||
%token <tagname> SQL_CONNECT SQL_OPEN
|
||||
%token <tagname> SQL_COMMIT SQL_ROLLBACK
|
||||
|
||||
%token <tagname> S_SYMBOL S_LENGTH S_ANYTHING
|
||||
%token <tagname> S_VARCHAR S_VARCHAR2
|
||||
%token <tagname> S_EXTERN S_STATIC
|
||||
%token <tagname> S_UNSIGNED S_SIGNED
|
||||
%token <tagname> S_LONG S_SHORT S_INT S_CHAR S_FLOAT S_DOUBLE S_BOOL
|
||||
%token <tagname> '[' ']' ';' ','
|
||||
|
||||
%type <type> type type_detailed varchar_type simple_type array_type
|
||||
%type <symbolname> symbol
|
||||
%type <tagname> maybe_storage_clause varchar_tag
|
||||
%type <type_enum> simple_tag
|
||||
%type <indexsize> index length
|
||||
%type <tagname> canything sqlanything both_anything
|
||||
|
||||
|
||||
%%
|
||||
prog : statements;
|
||||
|
||||
statements : /* empty */
|
||||
| statements statement;
|
||||
|
||||
statement : sqldeclaration
|
||||
| sqlinclude
|
||||
| sqlconnect
|
||||
| sqlopen
|
||||
| sqlcommit
|
||||
| sqlrollback
|
||||
| sqlstatement
|
||||
| cthing;
|
||||
|
||||
sqldeclaration : sql_startdeclare
|
||||
variable_declarations
|
||||
sql_enddeclare;
|
||||
|
||||
sql_startdeclare : SQL_START SQL_BEGIN SQL_DECLARE SQL_SECTION SQL_SEMI {
|
||||
fprintf(yyout, "/* exec sql begin declare section */\n");
|
||||
output_line_number();
|
||||
};
|
||||
sql_enddeclare : SQL_START SQL_END SQL_DECLARE SQL_SECTION SQL_SEMI {
|
||||
fprintf(yyout,"/* exec sql end declare section */\n");
|
||||
output_line_number();
|
||||
};
|
||||
|
||||
variable_declarations : /* empty */
|
||||
| variable_declarations variable_declaration ;
|
||||
|
||||
/* Here is where we can enter support for typedef. */
|
||||
variable_declaration : type ';' {
|
||||
new_variable($<type>1.name, $<type>1.typ);
|
||||
free($<type>1.name);
|
||||
fprintf(yyout, ";");
|
||||
}
|
||||
|
||||
symbol : S_SYMBOL {
|
||||
char * name = (char *)malloc(yyleng + 1);
|
||||
|
||||
strncpy(name, yytext, yyleng);
|
||||
name[yyleng] = '\0';
|
||||
|
||||
$<symbolname>$ = name;
|
||||
}
|
||||
|
||||
type : maybe_storage_clause type_detailed { $<type>$ = $<type>2; };
|
||||
type_detailed : varchar_type { $<type>$ = $<type>1; }
|
||||
| simple_type { $<type>$ = $<type>1; }
|
||||
| array_type {$<type>$ = $<type>1; };
|
||||
|
||||
varchar_type : varchar_tag symbol index {
|
||||
fprintf(yyout, "struct varchar_%s { int len; char arr[%d]; } %s", $<symbolname>2, $<indexsize>3, $<symbolname>2);
|
||||
$<type>$.name = $<symbolname>2;
|
||||
$<type>$.typ = ECPGmake_varchar_type(ECPGt_varchar, $<indexsize>3);
|
||||
}
|
||||
|
||||
varchar_tag : S_VARCHAR { $<tagname>$ = $<tagname>1; }
|
||||
| S_VARCHAR2 { $<tagname>$ = $<tagname>1; };
|
||||
|
||||
simple_type : simple_tag symbol {
|
||||
fprintf(yyout, "%s %s", ECPGtype_name($<type_enum>1), $<symbolname>2);
|
||||
$<type>$.name = $<symbolname>2;
|
||||
$<type>$.typ = ECPGmake_simple_type($<type_enum>1);
|
||||
}
|
||||
|
||||
array_type : simple_tag symbol index {
|
||||
fprintf(yyout, "%s %s [%d]", ECPGtype_name($<type_enum>1), $<symbolname>2, $<indexsize>3);
|
||||
$<type>$.name = $<symbolname>2;
|
||||
$<type>$.typ = ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), $<indexsize>3);
|
||||
}
|
||||
|
||||
simple_tag : S_CHAR { $<type_enum>$ = ECPGt_char; }
|
||||
| S_UNSIGNED S_CHAR { $<type_enum>$ = ECPGt_unsigned_char; }
|
||||
| S_SHORT { $<type_enum>$ = ECPGt_short; }
|
||||
| S_UNSIGNED S_SHORT { $<type_enum>$ = ECPGt_unsigned_short; }
|
||||
| S_INT { $<type_enum>$ = ECPGt_int; }
|
||||
| S_UNSIGNED S_INT { $<type_enum>$ = ECPGt_unsigned_int; }
|
||||
| S_LONG { $<type_enum>$ = ECPGt_long; }
|
||||
| S_UNSIGNED S_LONG { $<type_enum>$ = ECPGt_unsigned_long; }
|
||||
| S_FLOAT { $<type_enum>$ = ECPGt_float; }
|
||||
| S_DOUBLE { $<type_enum>$ = ECPGt_double; }
|
||||
| S_BOOL { $<type_enum>$ = ECPGt_bool; };
|
||||
|
||||
maybe_storage_clause : S_EXTERN { fwrite(yytext, yyleng, 1, yyout); }
|
||||
| S_STATIC { fwrite(yytext, yyleng, 1, yyout); }
|
||||
| /* empty */ { };
|
||||
|
||||
index : '[' length ']' {
|
||||
$<indexsize>$ = $<indexsize>2;
|
||||
};
|
||||
|
||||
length : S_LENGTH { $<indexsize>$ = atoi(yytext); }
|
||||
|
||||
sqlinclude : SQL_START SQL_INCLUDE { fprintf(yyout, "#include \""); }
|
||||
filename SQL_SEMI { fprintf(yyout, ".h\""); output_line_number(); };
|
||||
|
||||
filename : cthing
|
||||
| filename cthing;
|
||||
|
||||
sqlconnect : SQL_START SQL_CONNECT { fprintf(yyout, "ECPGconnect(\""); }
|
||||
SQL_STRING { fwrite(yytext + 1, yyleng - 2, 1, yyout); }
|
||||
SQL_SEMI { fprintf(yyout, "\");"); output_line_number(); };
|
||||
|
||||
/* Open is an open cursor. Removed. */
|
||||
sqlopen : SQL_START SQL_OPEN sqlgarbage SQL_SEMI { output_line_number(); };
|
||||
|
||||
sqlgarbage : /* Empty */
|
||||
| sqlgarbage sqlanything;
|
||||
|
||||
|
||||
sqlcommit : SQL_START SQL_COMMIT SQL_SEMI {
|
||||
fprintf(yyout, "ECPGcommit(__LINE__);");
|
||||
output_line_number();
|
||||
};
|
||||
sqlrollback : SQL_START SQL_ROLLBACK SQL_SEMI {
|
||||
fprintf(yyout, "ECPGrollback(__LINE__);");
|
||||
output_line_number();
|
||||
};
|
||||
|
||||
sqlstatement : SQL_START { /* Reset stack */
|
||||
reset_variables();
|
||||
fprintf(yyout, "ECPGdo(__LINE__, \"");
|
||||
}
|
||||
sqlstatement_words
|
||||
SQL_SEMI {
|
||||
/* Dump */
|
||||
fprintf(yyout, "\", ");
|
||||
dump_variables(argsinsert);
|
||||
fprintf(yyout, "ECPGt_EOIT, ");
|
||||
dump_variables(argsresult);
|
||||
fprintf(yyout, "ECPGt_EORT );");
|
||||
output_line_number();
|
||||
};
|
||||
|
||||
sqlstatement_words : sqlstatement_word
|
||||
| sqlstatement_words sqlstatement_word;
|
||||
|
||||
sqlstatement_word : ':' symbol
|
||||
{
|
||||
add_variable(&argsinsert, find_variable($2));
|
||||
fprintf(yyout, " ;; ");
|
||||
}
|
||||
| SQL_INTO into_list { }
|
||||
| sqlanything
|
||||
{
|
||||
fwrite(yytext, yyleng, 1, yyout);
|
||||
fwrite(" ", 1, 1, yyout);
|
||||
}
|
||||
| SQL_INTO sqlanything
|
||||
{
|
||||
fprintf(yyout, " into ");
|
||||
fwrite(yytext, yyleng, 1, yyout);
|
||||
fwrite(" ", 1, 1, yyout);
|
||||
};
|
||||
|
||||
into_list : ':' symbol {
|
||||
add_variable(&argsresult, find_variable($2));
|
||||
}
|
||||
| into_list ',' ':' symbol{
|
||||
add_variable(&argsresult, find_variable($4));
|
||||
};
|
||||
|
||||
cthing : canything {
|
||||
fwrite(yytext, yyleng, 1, yyout);
|
||||
}
|
||||
|
||||
canything : both_anything
|
||||
| SQL_INTO
|
||||
| ';';
|
||||
|
||||
sqlanything : both_anything;
|
||||
|
||||
both_anything : S_LENGTH | S_VARCHAR | S_VARCHAR2
|
||||
| S_LONG | S_SHORT | S_INT | S_CHAR | S_FLOAT | S_DOUBLE
|
||||
| SQL_OPEN | SQL_CONNECT
|
||||
| SQL_STRING
|
||||
| SQL_BEGIN | SQL_END
|
||||
| SQL_DECLARE | SQL_SECTION
|
||||
| SQL_INCLUDE
|
||||
| S_SYMBOL
|
||||
| '[' | ']' | ','
|
||||
| S_ANYTHING;
|
||||
|
||||
%%
|
||||
void yyerror(char * error)
|
||||
{
|
||||
fprintf(stderr, "%s\n", error);
|
||||
exit(1);
|
||||
}
|
||||
286
src/interfaces/ecpg/preproc/type.c
Normal file
286
src/interfaces/ecpg/preproc/type.c
Normal file
@@ -0,0 +1,286 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "type.h"
|
||||
|
||||
/* Constructors
|
||||
Yes, I mostly write c++-code
|
||||
*/
|
||||
|
||||
/* The NAME argument is copied. The type argument is preserved as a pointer. */
|
||||
struct ECPGrecord_member *
|
||||
ECPGmake_record_member(char * name, struct ECPGtype * type)
|
||||
{
|
||||
struct ECPGrecord_member * ne =
|
||||
(struct ECPGrecord_member *)malloc(sizeof(struct ECPGrecord_member));
|
||||
|
||||
ne->name = strdup(name);
|
||||
ne->typ = type;
|
||||
|
||||
return ne;
|
||||
}
|
||||
|
||||
struct ECPGtype *
|
||||
ECPGmake_simple_type(enum ECPGttype typ)
|
||||
{
|
||||
struct ECPGtype * ne = (struct ECPGtype *)malloc(sizeof(struct ECPGtype));
|
||||
|
||||
ne->typ = typ;
|
||||
ne->size = 0;
|
||||
ne->u.element = 0;
|
||||
|
||||
return ne;
|
||||
}
|
||||
|
||||
struct ECPGtype *
|
||||
ECPGmake_varchar_type(enum ECPGttype typ, unsigned short siz)
|
||||
{
|
||||
struct ECPGtype * ne = ECPGmake_simple_type(typ);
|
||||
|
||||
ne->size = siz;
|
||||
|
||||
return ne;
|
||||
}
|
||||
|
||||
struct ECPGtype *
|
||||
ECPGmake_array_type(struct ECPGtype * typ, unsigned short siz)
|
||||
{
|
||||
struct ECPGtype * ne = ECPGmake_simple_type(ECPGt_array);
|
||||
|
||||
ne->size = siz;
|
||||
ne->u.element = typ;
|
||||
|
||||
return ne;
|
||||
}
|
||||
|
||||
struct ECPGtype *
|
||||
ECPGmake_record_type(struct ECPGrecord_member * rm[])
|
||||
{
|
||||
struct ECPGtype * ne = ECPGmake_simple_type(ECPGt_record);
|
||||
|
||||
ne->u.members = rm;
|
||||
|
||||
return ne;
|
||||
}
|
||||
|
||||
|
||||
/* Dump a type.
|
||||
The type is dumped as:
|
||||
type-tag <comma> - enum ECPGttype
|
||||
reference-to-variable <comma> - void *
|
||||
size <comma> - short size of this field (if varchar)
|
||||
arrsize <comma> - short number of elements in the arr
|
||||
offset <comma> - short offset to the next element
|
||||
Where:
|
||||
type-tag is one of the simple types or varchar.
|
||||
reference-to-variable can be a reference to a struct element.
|
||||
arrsize is the size of the array in case of array fetches. Otherwise 0.
|
||||
size is the maxsize in case it is a varchar. Otherwise it is the size of
|
||||
the variable (required to do array fetches of records).
|
||||
*/
|
||||
void ECPGdump_a_simple(FILE * o, const char * name, enum ECPGttype typ,
|
||||
short varcharsize,
|
||||
unsigned short arrsiz, const char * siz);
|
||||
void ECPGdump_a_record(FILE * o, const char * name, unsigned short arrsiz,
|
||||
struct ECPGtype * typ, const char * offset);
|
||||
|
||||
|
||||
void
|
||||
ECPGdump_a_type(FILE * o, const char * name, struct ECPGtype * typ)
|
||||
{
|
||||
if (IS_SIMPLE_TYPE(typ->typ))
|
||||
{
|
||||
ECPGdump_a_simple(o, name, typ->typ, typ->size, 0, 0);
|
||||
}
|
||||
else if (typ->typ == ECPGt_array)
|
||||
{
|
||||
if (IS_SIMPLE_TYPE(typ->u.element->typ))
|
||||
ECPGdump_a_simple(o, name, typ->u.element->typ,
|
||||
typ->u.element->size, typ->size, 0);
|
||||
else if (typ->u.element->typ == ECPGt_array)
|
||||
{
|
||||
abort(); /* Array of array, */
|
||||
}
|
||||
else if (typ->u.element->typ == ECPGt_record)
|
||||
{
|
||||
/* Array of records. */
|
||||
ECPGdump_a_record(o, name, typ->size, typ->u.element, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
abort();
|
||||
}
|
||||
}
|
||||
else if (typ->typ == ECPGt_record)
|
||||
{
|
||||
ECPGdump_a_record(o, name, 0, typ, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* If siz is NULL, then the offset is 0, if not use siz as a
|
||||
string, it represents the offset needed if we are in an array of records. */
|
||||
void
|
||||
ECPGdump_a_simple(FILE * o, const char * name, enum ECPGttype typ,
|
||||
short varcharsize,
|
||||
unsigned short arrsiz,
|
||||
const char * siz)
|
||||
{
|
||||
switch (typ)
|
||||
{
|
||||
case ECPGt_char:
|
||||
fprintf(o, "\n\tECPGt_char,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(char)" : siz);
|
||||
break;
|
||||
case ECPGt_unsigned_char:
|
||||
fprintf(o, "\n\tECPGt_unsigned_char,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(unsigned char)" : siz);
|
||||
break;
|
||||
case ECPGt_short:
|
||||
fprintf(o, "\n\tECPGt_short,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(short)" : siz);
|
||||
break;
|
||||
case ECPGt_unsigned_short:
|
||||
fprintf(o,
|
||||
"\n\tECPGt_unsigned_short,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(unsigned short)" : siz);
|
||||
break;
|
||||
case ECPGt_int:
|
||||
fprintf(o, "\n\tECPGt_int,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(int)" : siz);
|
||||
break;
|
||||
case ECPGt_unsigned_int:
|
||||
fprintf(o, "\n\tECPGt_unsigned_int,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(unsigned int)" : siz);
|
||||
break;
|
||||
case ECPGt_long:
|
||||
fprintf(o, "\n\tECPGt_long,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(long)" : siz);
|
||||
break;
|
||||
case ECPGt_unsigned_long:
|
||||
fprintf(o, "\n\tECPGt_unsigned_int,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(unsigned int)" : siz);
|
||||
break;
|
||||
case ECPGt_float:
|
||||
fprintf(o, "\n\tECPGt_float,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(float)" : siz);
|
||||
break;
|
||||
case ECPGt_double:
|
||||
fprintf(o, "\n\tECPGt_double,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(double)" : siz);
|
||||
break;
|
||||
case ECPGt_bool:
|
||||
fprintf(o, "\n\tECPGt_bool,&%s,0,%d,%s, ", name, arrsiz,
|
||||
siz == NULL ? "sizeof(bool)" : siz);
|
||||
break;
|
||||
case ECPGt_varchar:
|
||||
case ECPGt_varchar2:
|
||||
if (siz == NULL)
|
||||
fprintf(o, "\n\tECPGt_varchar,&%s,%d,%d,sizeof(struct varchar_%s), ",
|
||||
name,
|
||||
varcharsize,
|
||||
arrsiz, name);
|
||||
else
|
||||
fprintf(o, "\n\tECPGt_varchar,&%s,%d,%d,%s, ",
|
||||
name,
|
||||
varcharsize,
|
||||
arrsiz, siz);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Penetrate a record and dump the contents. */
|
||||
void
|
||||
ECPGdump_a_record(FILE * o,
|
||||
const char * name, unsigned short arrsiz,
|
||||
struct ECPGtype * typ, const char * offsetarg)
|
||||
{
|
||||
/* If offset is NULL, then this is the first recursive level. If not then
|
||||
we are in a record in a record and the offset is used as offset.
|
||||
*/
|
||||
struct ECPGrecord_member ** p;
|
||||
char obuf[BUFSIZ];
|
||||
char buf[BUFSIZ];
|
||||
const char * offset;
|
||||
|
||||
if (offsetarg == NULL)
|
||||
{
|
||||
sprintf(obuf, "sizeof(%s)", name);
|
||||
offset = obuf;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = offsetarg;
|
||||
}
|
||||
|
||||
for (p = typ->u.members; *p; p++)
|
||||
{
|
||||
if (IS_SIMPLE_TYPE((*p)->typ->typ))
|
||||
{
|
||||
sprintf(buf, "%s.%s", name, (*p)->name);
|
||||
ECPGdump_a_simple(o, buf, (*p)->typ->typ, (*p)->typ->size,
|
||||
arrsiz, offset);
|
||||
}
|
||||
else if ((*p)->typ->typ == ECPGt_array)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (*p)->typ->size; i++)
|
||||
{
|
||||
if (IS_SIMPLE_TYPE((*p)->typ->u.element->typ))
|
||||
{
|
||||
sprintf(buf, "%s.%s[%d]", name, (*p)->name, i);
|
||||
ECPGdump_a_simple(o, buf, (*p)->typ->typ, (*p)->typ->size,
|
||||
arrsiz, offset);
|
||||
}
|
||||
else if((*p)->typ->u.element->typ == ECPGt_array)
|
||||
{
|
||||
/* Array within an array. NOT implemented yet. */
|
||||
abort();
|
||||
}
|
||||
else if ((*p)->typ->u.element->typ == ECPGt_record)
|
||||
{
|
||||
/* Record within array within record. NOT implemented yet. */
|
||||
abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unknown type */
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((*p)->typ->typ == ECPGt_record)
|
||||
{
|
||||
/* Record within a record */
|
||||
sprintf(buf, "%s.%s", name, (*p)->name);
|
||||
ECPGdump_a_record(o, buf, arrsiz, (*p)->typ, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unknown type */
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Freeing is not really that important. Since we throw away the process
|
||||
anyway. Lets implement that last! */
|
||||
|
||||
void
|
||||
ECPGfree_record_member(struct ECPGrecord_member * rm)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ECPGfree_type(struct ECPGtype * typ)
|
||||
{
|
||||
}
|
||||
51
src/interfaces/ecpg/preproc/type.h
Normal file
51
src/interfaces/ecpg/preproc/type.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#include <ecpgtype.h>
|
||||
|
||||
struct ECPGtype;
|
||||
struct ECPGrecord_member {
|
||||
char * name;
|
||||
struct ECPGtype * typ;
|
||||
};
|
||||
struct ECPGtype {
|
||||
enum ECPGttype typ;
|
||||
unsigned short size; /* For array it is the number of elements.
|
||||
* For varchar it is the maxsize of the area.
|
||||
*/
|
||||
union {
|
||||
struct ECPGtype * element; /* For an array this is the type of the
|
||||
* element */
|
||||
|
||||
struct ECPGrecord_member ** members;
|
||||
/* A pointer to an array of members. */
|
||||
} u;
|
||||
};
|
||||
|
||||
/* Everything is malloced. */
|
||||
struct ECPGrecord_member * ECPGmake_record_member(char *, struct ECPGtype *);
|
||||
struct ECPGtype * ECPGmake_simple_type(enum ECPGttype);
|
||||
struct ECPGtype * ECPGmake_varchar_type(enum ECPGttype, unsigned short);
|
||||
struct ECPGtype * ECPGmake_array_type(struct ECPGtype *, unsigned short);
|
||||
struct ECPGtype * ECPGmake_record_type(struct ECPGrecord_member *[]);
|
||||
|
||||
/* Frees a type. */
|
||||
void ECPGfree_record_member(struct ECPGrecord_member *);
|
||||
void ECPGfree_type(struct ECPGtype *);
|
||||
|
||||
/* Dump a type.
|
||||
The type is dumped as:
|
||||
type-tag <comma> reference-to-variable <comma> arrsize <comma> size <comma>
|
||||
Where:
|
||||
type-tag is one of the simple types or varchar.
|
||||
reference-to-variable can be a reference to a struct element.
|
||||
arrsize is the size of the array in case of array fetches. Otherwise 0.
|
||||
size is the maxsize in case it is a varchar. Otherwise it is the size of
|
||||
the variable (required to do array fetches of records).
|
||||
*/
|
||||
void ECPGdump_a_type(FILE *, const char * name, struct ECPGtype *);
|
||||
|
||||
/* A simple struct to keep a variable and its type. */
|
||||
struct ECPGtemp_type {
|
||||
struct ECPGtype * typ;
|
||||
const char * name;
|
||||
};
|
||||
|
||||
extern const char * ECPGtype_name(enum ECPGttype typ);
|
||||
39
src/interfaces/ecpg/preproc/y.tab.h
Normal file
39
src/interfaces/ecpg/preproc/y.tab.h
Normal file
@@ -0,0 +1,39 @@
|
||||
typedef union {
|
||||
int tagname;
|
||||
struct ECPGtemp_type type;
|
||||
char * symbolname;
|
||||
int indexsize;
|
||||
enum ECPGttype type_enum;
|
||||
} YYSTYPE;
|
||||
#define SQL_START 258
|
||||
#define SQL_SEMI 259
|
||||
#define SQL_STRING 260
|
||||
#define SQL_INTO 261
|
||||
#define SQL_BEGIN 262
|
||||
#define SQL_END 263
|
||||
#define SQL_DECLARE 264
|
||||
#define SQL_SECTION 265
|
||||
#define SQL_INCLUDE 266
|
||||
#define SQL_CONNECT 267
|
||||
#define SQL_OPEN 268
|
||||
#define SQL_COMMIT 269
|
||||
#define SQL_ROLLBACK 270
|
||||
#define S_SYMBOL 271
|
||||
#define S_LENGTH 272
|
||||
#define S_ANYTHING 273
|
||||
#define S_VARCHAR 274
|
||||
#define S_VARCHAR2 275
|
||||
#define S_EXTERN 276
|
||||
#define S_STATIC 277
|
||||
#define S_UNSIGNED 278
|
||||
#define S_SIGNED 279
|
||||
#define S_LONG 280
|
||||
#define S_SHORT 281
|
||||
#define S_INT 282
|
||||
#define S_CHAR 283
|
||||
#define S_FLOAT 284
|
||||
#define S_DOUBLE 285
|
||||
#define S_BOOL 286
|
||||
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
Reference in New Issue
Block a user