diff options
author | Michael Meskes <meskes@postgresql.org> | 2000-02-17 19:48:58 +0000 |
---|---|---|
committer | Michael Meskes <meskes@postgresql.org> | 2000-02-17 19:48:58 +0000 |
commit | b3b35e98b67d51d6e21dd06e5342c3c46074fa4f (patch) | |
tree | 3b086b1da683037632c3a8fdfcc4acfa20237774 /src/interfaces/ecpg/preproc/variable.c | |
parent | 3ca3bb7d8b00d4ac9f9b6e1edef28d0aa17e7206 (diff) | |
download | postgresql-b3b35e98b67d51d6e21dd06e5342c3c46074fa4f.tar.gz postgresql-b3b35e98b67d51d6e21dd06e5342c3c46074fa4f.zip |
*** empty log message ***
Diffstat (limited to 'src/interfaces/ecpg/preproc/variable.c')
-rw-r--r-- | src/interfaces/ecpg/preproc/variable.c | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/src/interfaces/ecpg/preproc/variable.c b/src/interfaces/ecpg/preproc/variable.c new file mode 100644 index 00000000000..df458dcc070 --- /dev/null +++ b/src/interfaces/ecpg/preproc/variable.c @@ -0,0 +1,358 @@ +#include "postgres.h" + +#include "extern.h" + +struct variable * allvariables = NULL; + +struct variable * +new_variable(const char * name, struct ECPGtype * type) +{ + struct variable * p = (struct variable*) mm_alloc(sizeof(struct variable)); + + p->name = mm_strdup(name); + p->type = type; + p->brace_level = braces_open; + + p->next = allvariables; + allvariables = p; + + return(p); +} + +static struct variable * +find_struct_member(char *name, char *str, struct ECPGstruct_member *members) +{ + char *next = strchr(++str, '.'), c = '\0'; + + if (next != NULL) + { + c = *next; + *next = '\0'; + } + + for (; members; members = members->next) + { + if (strcmp(members->name, str) == 0) + { + if (c == '\0') + { + /* found the end */ + switch (members->typ->typ) + { + case ECPGt_array: + return(new_variable(name, ECPGmake_array_type(members->typ->u.element, members->typ->size))); + case ECPGt_struct: + case ECPGt_union: + return(new_variable(name, ECPGmake_struct_type(members->typ->u.members, members->typ->typ))); + default: + return(new_variable(name, ECPGmake_simple_type(members->typ->typ, members->typ->size))); + } + } + else + { + *next = c; + if (c == '-') + { + next++; + return(find_struct_member(name, next, members->typ->u.element->u.members)); + } + else return(find_struct_member(name, next, members->typ->u.members)); + } + } + } + + return(NULL); +} + +static struct variable * +find_struct(char * name, char *next) +{ + struct variable * p; + char c = *next; + + /* first get the mother structure entry */ + *next = '\0'; + p = find_variable(name); + + if (c == '-') + { + if (p->type->typ != ECPGt_struct && p->type->typ != ECPGt_union) + { + sprintf(errortext, "variable %s is not a pointer", name); + mmerror(ET_FATAL, errortext); + } + + if (p->type->u.element->typ != ECPGt_struct && p->type->u.element->typ != ECPGt_union) + { + sprintf(errortext, "variable %s is not a pointer to a structure or a union", name); + mmerror(ET_FATAL, errortext); + } + + /* restore the name, we will need it later on */ + *next = c; + next++; + + return find_struct_member(name, next, p->type->u.element->u.members); + } + else + { + if (p->type->typ != ECPGt_struct && p->type->typ != ECPGt_union) + { + sprintf(errortext, "variable %s is neither a structure nor a union", name); + mmerror(ET_FATAL, errortext); + } + + /* restore the name, we will need it later on */ + *next = c; + + return find_struct_member(name, next, p->type->u.members); + } +} + +static struct variable * +find_simple(char * name) +{ + struct variable * p; + + for (p = allvariables; p; p = p->next) + { + if (strcmp(p->name, name) == 0) + return p; + } + + return(NULL); +} + +/* Note that this function will end the program in case of an unknown */ +/* variable */ +struct variable * +find_variable(char * name) +{ + char * next; + struct variable * p; + + if ((next = strchr(name, '.')) != NULL) + p = find_struct(name, next); + else if ((next = strstr(name, "->")) != NULL) + p = find_struct(name, next); + else + p = find_simple(name); + + if (p == NULL) + { + sprintf(errortext, "The variable %s is not declared", name); + mmerror(ET_FATAL, errortext); + } + + return(p); +} + +void +remove_variables(int brace_level) +{ + struct variable * p, *prev; + + for (p = prev = allvariables; p; p = p ? p->next : NULL) + { + if (p->brace_level >= brace_level) + { + /* remove it */ + if (p == allvariables) + prev = allvariables = p->next; + else + prev->next = p->next; + + ECPGfree_type(p->type); + free(p->name); + free(p); + p = prev; + } + else + prev = p; + } +} + + +/* + * Here are 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 * argsinsert = NULL; +struct arguments * argsresult = NULL; + +void +reset_variables(void) +{ + argsinsert = NULL; + argsresult = NULL; +} + + +/* Add a variable to a request. */ +void +add_variable(struct arguments ** list, struct variable * var, struct variable * ind) +{ + struct arguments * p = (struct arguments *)mm_alloc(sizeof(struct arguments)); + p->variable = var; + p->indicator = ind; + 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, int mode) +{ + 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, mode); + + /* Then the current element and its indicator */ + ECPGdump_a_type(yyout, list->variable->name, list->variable->type, + (list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->name : NULL, + (list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->type : NULL, NULL, NULL); + + /* Then release the list element. */ + if (mode != 0) + free(list); +} + +void +check_indicator(struct ECPGtype *var) +{ + /* make sure this is a valid indicator variable */ + switch (var->typ) + { + struct ECPGstruct_member *p; + + case ECPGt_short: + case ECPGt_int: + case ECPGt_long: + case ECPGt_unsigned_short: + case ECPGt_unsigned_int: + case ECPGt_unsigned_long: + break; + + case ECPGt_struct: + case ECPGt_union: + for (p = var->u.members; p; p = p->next) + check_indicator(p->typ); + break; + + case ECPGt_array: + check_indicator(var->u.element); + break; + default: + mmerror(ET_ERROR, "indicator variable must be integer type"); + break; + } +} + +struct typedefs * +get_typedef(char *name) +{ + struct typedefs *this; + + for (this = types; this && strcmp(this->name, name); this = this->next); + if (!this) + { + sprintf(errortext, "invalid datatype '%s'", name); + mmerror(ET_FATAL, errortext); + } + + return(this); +} + +void +adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dimension, int type_index, bool pointer) +{ + if (type_index >= 0) + { + if (*length >= 0) + mmerror(ET_FATAL, "No multi-dimensional array support"); + + *length = type_index; + } + + if (type_dimension >= 0) + { + if (*dimension >= 0 && *length >= 0) + mmerror(ET_FATAL, "No multi-dimensional array support"); + + if (*dimension >= 0) + *length = *dimension; + + *dimension = type_dimension; + } + + if (*length >= 0 && *dimension >= 0 && pointer) + mmerror(ET_FATAL, "No multi-dimensional array support"); + + switch (type_enum) + { + case ECPGt_struct: + case ECPGt_union: + /* pointer has to get dimension 0 */ + if (pointer) + { + *length = *dimension; + *dimension = 0; + } + + if (*length >= 0) + mmerror(ET_FATAL, "No multi-dimensional array support for structures"); + + break; + case ECPGt_varchar: + /* pointer has to get dimension 0 */ + if (pointer) + *dimension = 0; + + /* one index is the string length */ + if (*length < 0) + { + *length = *dimension; + *dimension = -1; + } + + break; + case ECPGt_char: + case ECPGt_unsigned_char: + /* pointer has to get length 0 */ + if (pointer) + *length=0; + + /* one index is the string length */ + if (*length < 0) + { + *length = (*dimension < 0) ? 1 : *dimension; + *dimension = -1; + } + + break; + default: + /* a pointer has dimension = 0 */ + if (pointer) { + *length = *dimension; + *dimension = 0; + } + + if (*length >= 0) + mmerror(ET_FATAL, "No multi-dimensional array support for simple data types"); + + break; + } +} |