1
0
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:
Marc G. Fournier
1998-02-10 16:44:17 +00:00
parent a8313f9671
commit 38201e21d0
31 changed files with 985 additions and 778 deletions

View 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

View 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

View 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);
}

View 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;
}

View 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);
}

View 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)
{
}

View 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);

View 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;