1998-02-05 16:46:43 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
1998-02-17 02:48:12 +01:00
|
|
|
#include <stdlib.h>
|
1998-02-05 16:46:43 +01:00
|
|
|
|
|
|
|
#include "type.h"
|
|
|
|
|
1998-02-17 02:48:12 +01:00
|
|
|
/* malloc + error check */
|
|
|
|
void *mm_alloc(size_t size)
|
|
|
|
{
|
|
|
|
void *ptr = malloc(size);
|
|
|
|
|
|
|
|
if (ptr == NULL)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Out of memory\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ptr);
|
|
|
|
}
|
|
|
|
|
1998-02-05 16:46:43 +01:00
|
|
|
/* Constructors
|
|
|
|
Yes, I mostly write c++-code
|
1998-02-17 02:48:12 +01:00
|
|
|
*/
|
1998-02-05 16:46:43 +01:00
|
|
|
|
|
|
|
/* The NAME argument is copied. The type argument is preserved as a pointer. */
|
|
|
|
struct ECPGrecord_member *
|
1998-02-17 02:48:12 +01:00
|
|
|
ECPGmake_record_member(char *name, struct ECPGtype *type, struct ECPGrecord_member **start)
|
1998-02-05 16:46:43 +01:00
|
|
|
{
|
1998-02-17 02:48:12 +01:00
|
|
|
struct ECPGrecord_member *ptr, *ne =
|
|
|
|
(struct ECPGrecord_member *) mm_alloc(sizeof(struct ECPGrecord_member));
|
|
|
|
|
|
|
|
ne->name = strdup(name);
|
|
|
|
ne->typ = type;
|
|
|
|
ne->next = NULL;
|
1998-02-05 16:46:43 +01:00
|
|
|
|
1998-02-17 02:48:12 +01:00
|
|
|
for (ptr = *start; ptr && ptr->next; ptr = ptr->next);
|
1998-02-05 16:46:43 +01:00
|
|
|
|
1998-02-17 02:48:12 +01:00
|
|
|
if (ptr)
|
|
|
|
ptr->next=ne;
|
|
|
|
else
|
|
|
|
*start=ne;
|
|
|
|
return ne;
|
1998-02-05 16:46:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
struct ECPGtype *
|
|
|
|
ECPGmake_simple_type(enum ECPGttype typ)
|
|
|
|
{
|
1998-02-17 02:48:12 +01:00
|
|
|
struct ECPGtype *ne = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
|
1998-02-05 16:46:43 +01:00
|
|
|
|
1998-02-17 02:48:12 +01:00
|
|
|
ne->typ = typ;
|
|
|
|
ne->size = 0;
|
|
|
|
ne->u.element = 0;
|
1998-02-05 16:46:43 +01:00
|
|
|
|
1998-02-17 02:48:12 +01:00
|
|
|
return ne;
|
1998-02-05 16:46:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
struct ECPGtype *
|
|
|
|
ECPGmake_varchar_type(enum ECPGttype typ, unsigned short siz)
|
|
|
|
{
|
1998-02-17 02:48:12 +01:00
|
|
|
struct ECPGtype *ne = ECPGmake_simple_type(typ);
|
1998-02-05 16:46:43 +01:00
|
|
|
|
1998-02-17 02:48:12 +01:00
|
|
|
ne->size = siz;
|
1998-02-05 16:46:43 +01:00
|
|
|
|
1998-02-17 02:48:12 +01:00
|
|
|
return ne;
|
1998-02-05 16:46:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
struct ECPGtype *
|
1998-02-17 02:48:12 +01:00
|
|
|
ECPGmake_array_type(struct ECPGtype *typ, unsigned short siz)
|
1998-02-05 16:46:43 +01:00
|
|
|
{
|
1998-02-17 02:48:12 +01:00
|
|
|
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array);
|
1998-02-05 16:46:43 +01:00
|
|
|
|
1998-02-17 02:48:12 +01:00
|
|
|
ne->size = siz;
|
|
|
|
ne->u.element = typ;
|
1998-02-05 16:46:43 +01:00
|
|
|
|
1998-02-17 02:48:12 +01:00
|
|
|
return ne;
|
1998-02-05 16:46:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
struct ECPGtype *
|
1998-02-17 02:48:12 +01:00
|
|
|
ECPGmake_record_type(struct ECPGrecord_member *rm)
|
1998-02-05 16:46:43 +01:00
|
|
|
{
|
1998-02-17 02:48:12 +01:00
|
|
|
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_record);
|
1998-02-05 16:46:43 +01:00
|
|
|
|
1998-02-17 02:48:12 +01:00
|
|
|
ne->u.members = rm;
|
1998-02-05 16:46:43 +01:00
|
|
|
|
1998-02-17 02:48:12 +01:00
|
|
|
return ne;
|
1998-02-05 16:46:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Dump a type.
|
|
|
|
The type is dumped as:
|
1998-02-17 02:48:12 +01:00
|
|
|
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
|
1998-02-05 16:46:43 +01:00
|
|
|
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
|
1998-02-17 02:48:12 +01:00
|
|
|
the variable (required to do array fetches of records).
|
1998-02-05 16:46:43 +01:00
|
|
|
*/
|
1998-02-17 02:48:12 +01:00
|
|
|
void ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
|
|
|
|
short varcharsize,
|
|
|
|
unsigned short arrsiz, const char *siz, const char *prefix);
|
|
|
|
void ECPGdump_a_record(FILE *o, const char *name, unsigned short arrsiz,
|
|
|
|
struct ECPGtype *typ, const char *offset, const char *prefix);
|
1998-02-05 16:46:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
void
|
1998-02-17 02:48:12 +01:00
|
|
|
ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype *typ, const char *prefix)
|
1998-02-05 16:46:43 +01:00
|
|
|
{
|
1998-02-17 02:48:12 +01:00
|
|
|
if (IS_SIMPLE_TYPE(typ->typ))
|
|
|
|
{
|
|
|
|
ECPGdump_a_simple(o, name, typ->typ, typ->size, 0, 0, prefix);
|
|
|
|
}
|
|
|
|
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, prefix);
|
|
|
|
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, prefix);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (typ->typ == ECPGt_record)
|
|
|
|
{
|
|
|
|
ECPGdump_a_record(o, name, 0, typ, 0, prefix);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
abort();
|
|
|
|
}
|
1998-02-05 16:46:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 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
|
1998-02-17 02:48:12 +01:00
|
|
|
ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
|
|
|
|
short varcharsize,
|
|
|
|
unsigned short arrsiz,
|
|
|
|
const char *siz,
|
|
|
|
const char *prefix)
|
1998-02-05 16:46:43 +01:00
|
|
|
{
|
1998-02-17 02:48:12 +01:00
|
|
|
switch (typ)
|
|
|
|
{
|
|
|
|
case ECPGt_char:
|
|
|
|
fprintf(o, "\n\tECPGt_char,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz,
|
|
|
|
siz == NULL ? "sizeof(char)" : siz);
|
|
|
|
break;
|
|
|
|
case ECPGt_unsigned_char:
|
|
|
|
fprintf(o, "\n\tECPGt_unsigned_char,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz,
|
|
|
|
siz == NULL ? "sizeof(unsigned char)" : siz);
|
|
|
|
break;
|
|
|
|
case ECPGt_short:
|
|
|
|
fprintf(o, "\n\tECPGt_short,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz,
|
|
|
|
siz == NULL ? "sizeof(short)" : siz);
|
|
|
|
break;
|
|
|
|
case ECPGt_unsigned_short:
|
|
|
|
fprintf(o,
|
|
|
|
"\n\tECPGt_unsigned_short,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz,
|
|
|
|
siz == NULL ? "sizeof(unsigned short)" : siz);
|
|
|
|
break;
|
|
|
|
case ECPGt_int:
|
|
|
|
fprintf(o, "\n\tECPGt_int,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz,
|
|
|
|
siz == NULL ? "sizeof(int)" : siz);
|
|
|
|
break;
|
|
|
|
case ECPGt_unsigned_int:
|
|
|
|
fprintf(o, "\n\tECPGt_unsigned_int,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz,
|
|
|
|
siz == NULL ? "sizeof(unsigned int)" : siz);
|
|
|
|
break;
|
|
|
|
case ECPGt_long:
|
|
|
|
fprintf(o, "\n\tECPGt_long,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz,
|
|
|
|
siz == NULL ? "sizeof(long)" : siz);
|
|
|
|
break;
|
|
|
|
case ECPGt_unsigned_long:
|
|
|
|
fprintf(o, "\n\tECPGt_unsigned_int,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz,
|
|
|
|
siz == NULL ? "sizeof(unsigned int)" : siz);
|
|
|
|
break;
|
|
|
|
case ECPGt_float:
|
|
|
|
fprintf(o, "\n\tECPGt_float,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz,
|
|
|
|
siz == NULL ? "sizeof(float)" : siz);
|
|
|
|
break;
|
|
|
|
case ECPGt_double:
|
|
|
|
fprintf(o, "\n\tECPGt_double,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz,
|
|
|
|
siz == NULL ? "sizeof(double)" : siz);
|
|
|
|
break;
|
|
|
|
case ECPGt_bool:
|
|
|
|
fprintf(o, "\n\tECPGt_bool,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz,
|
|
|
|
siz == NULL ? "sizeof(bool)" : siz);
|
|
|
|
break;
|
|
|
|
case ECPGt_varchar:
|
|
|
|
case ECPGt_varchar2:
|
|
|
|
if (siz == NULL)
|
|
|
|
fprintf(o, "\n\tECPGt_varchar,&%s%s,%d,%d,sizeof(struct varchar_%s), ",
|
|
|
|
prefix ? prefix : "", name,
|
|
|
|
varcharsize,
|
|
|
|
arrsiz, name);
|
|
|
|
else
|
|
|
|
fprintf(o, "\n\tECPGt_varchar,&%s%s,%d,%d,%s, ",
|
|
|
|
prefix ? prefix : "", name,
|
|
|
|
varcharsize,
|
|
|
|
arrsiz, siz);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
abort();
|
|
|
|
}
|
1998-02-05 16:46:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Penetrate a record and dump the contents. */
|
|
|
|
void
|
1998-02-17 02:48:12 +01:00
|
|
|
ECPGdump_a_record(FILE *o, const char *name, unsigned short arrsiz, struct ECPGtype *typ, const char *offsetarg, const char *prefix)
|
1998-02-05 16:46:43 +01:00
|
|
|
{
|
1998-02-17 02:48:12 +01:00
|
|
|
/* 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 pbuf[BUFSIZ];
|
|
|
|
const char *offset;
|
|
|
|
|
|
|
|
if (offsetarg == NULL)
|
|
|
|
{
|
|
|
|
sprintf(obuf, "sizeof(%s)", name);
|
|
|
|
offset = obuf;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
offset = offsetarg;
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf(pbuf, "%s%s.", prefix ? prefix : "", name);
|
|
|
|
prefix = pbuf;
|
|
|
|
|
|
|
|
for (p = typ->u.members; p; p=p->next)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
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); */
|
|
|
|
sprintf(buf, "%s.%s", name, p->name);
|
|
|
|
ECPGdump_a_simple(o, buf, p->typ->u.element->typ, p->typ->u.element->size,
|
|
|
|
p->typ->u.element->size, offset);
|
|
|
|
}
|
|
|
|
else if (p->typ->u.element->typ == ECPGt_array)
|
|
|
|
{
|
|
|
|
/* Array within an array. NOT implemented. */
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
ECPGdump_a_type(o, p->name, p->typ, prefix);
|
|
|
|
}
|
1998-02-05 16:46:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Freeing is not really that important. Since we throw away the process
|
|
|
|
anyway. Lets implement that last! */
|
|
|
|
|
|
|
|
void
|
1998-02-17 02:48:12 +01:00
|
|
|
ECPGfree_record_member(struct ECPGrecord_member *rm)
|
1998-02-05 16:46:43 +01:00
|
|
|
{
|
1998-02-17 02:48:12 +01:00
|
|
|
while (rm)
|
|
|
|
{
|
|
|
|
struct ECPGrecord_member *p = rm;
|
|
|
|
|
|
|
|
rm = rm->next;
|
|
|
|
free(p->name);
|
|
|
|
free(p);
|
|
|
|
}
|
1998-02-05 16:46:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-02-17 02:48:12 +01:00
|
|
|
ECPGfree_type(struct ECPGtype *typ)
|
1998-02-05 16:46:43 +01:00
|
|
|
{
|
1998-02-17 02:48:12 +01:00
|
|
|
if (!IS_SIMPLE_TYPE(typ->typ))
|
|
|
|
{
|
|
|
|
if (typ->typ == ECPGt_array)
|
|
|
|
{
|
|
|
|
if (IS_SIMPLE_TYPE(typ->u.element->typ))
|
|
|
|
free(typ->u.element);
|
|
|
|
else if (typ->u.element->typ == ECPGt_array)
|
|
|
|
abort(); /* Array of array, */
|
|
|
|
else if (typ->u.element->typ == ECPGt_record)
|
|
|
|
/* Array of records. */
|
|
|
|
ECPGfree_record_member(typ->u.members);
|
|
|
|
else
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
else if (typ->typ == ECPGt_record)
|
|
|
|
{
|
|
|
|
ECPGfree_record_member(typ->u.members);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(typ);
|
1998-02-05 16:46:43 +01:00
|
|
|
}
|