Tue May 27 16:33:36 CEST 2003
- Accept stdin/stdout as input/output file.
+
+Thu May 29 13:58:25 CEST 2003
+
+ - ecpg should now be able to parse forward struct definition.
- Set ecpg version to 2.12.0.
- Set ecpg library to 3.4.2.
- Set pgtypes library to 1.0.0
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.111 2003/05/27 14:36:00 meskes Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.112 2003/05/29 12:00:21 meskes Exp $
*
*-------------------------------------------------------------------------
*/
identifier {letter}{letter_or_digit}*
+array ({letter_or_digit}|[\+\-\*\%\/\(\)])*
typecast "::"
/*
<incl>\<[^\>]+\>{space}*";"? { parse_include(); }
<incl>{dquote}{xdinside}{dquote}{space}*";"? { parse_include(); }
-<incl>[^;\<\>\"]+";" {
- parse_include();
-#if 0
- /* got the include file name */
- struct _yy_buffer *yb;
- struct _include_path *ip;
- char inc_file[MAXPGPATH];
- unsigned int i;
-
- yb = mm_alloc(sizeof(struct _yy_buffer));
-
- yb->buffer = YY_CURRENT_BUFFER;
- yb->lineno = yylineno;
- yb->filename = input_filename;
- yb->next = yy_buffer;
-
- yy_buffer = yb;
-
- /*
- * skip the ";" and trailing whitespace. Note that yytext contains
- * at least one non-space character plus the ";"
- */
- for ( i = strlen(yytext)-2;
- i > 0 && isspace((unsigned char) yytext[i]);
- i-- )
- {}
-
- yytext[i+1] = '\0';
- yyin = NULL;
-
- /* If file name is enclosed in '"' remove these and look only in '.' */
- /* Informix does look into all include paths though, except filename starts with '/' */
- if ((yytext[0] == '"' && yytext[i] == '"') && (compat != ECPG_COMPAT_INFORMIX || yytext[0] == '/'))
- {
- yytext[i] = '\0';
- memmove(yytext, yytext+1, strlen(yytext));
-
- strncpy(inc_file, yytext, sizeof(inc_file));
- yyin = fopen(inc_file, "r");
- if (!yyin)
- {
- if (strcmp(inc_file + strlen(inc_file) - 2, ".h"))
- {
- strcat(inc_file, ".h");
- yyin = fopen(inc_file, "r");
- }
- }
-
- }
- else
- {
- if (yytext[0] == '"' && yytext[i] == '"')
- {
- yytext[i] = '\0';
- memmove(yytext, yytext+1, strlen(yytext));
- }
-
- for (ip = include_paths; yyin == NULL && ip != NULL; ip = ip->next)
- {
- if (strlen(ip->path) + strlen(yytext) + 3 > MAXPGPATH)
- {
- fprintf(stderr, "Error: Path %s/%s is too long in line %d, skipping.\n", ip->path, yytext, yylineno);
- continue;
- }
- snprintf (inc_file, sizeof(inc_file), "%s/%s", ip->path, yytext);
- yyin = fopen(inc_file, "r");
- if (!yyin)
- {
- if (strcmp(inc_file + strlen(inc_file) - 2, ".h"))
- {
- strcat(inc_file, ".h");
- yyin = fopen( inc_file, "r" );
- }
- }
- }
- }
- if (!yyin)
- {
- snprintf(errortext, sizeof(errortext), "Cannot open include file %s in line %d\n", yytext, yylineno);
- mmerror(NO_INCLUDE_FILE, ET_FATAL, errortext);
- }
-
- input_filename = mm_strdup(inc_file);
- yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE ));
- yylineno = 1;
- output_line_number();
-
- BEGIN C;
-#endif
- }
+<incl>[^;\<\>\"]+";" { parse_include(); }
<<EOF>> {
if (yy_buffer == NULL) {
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.223 2003/05/27 11:31:52 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.224 2003/05/29 12:00:21 meskes Exp $ */
/* Copyright comment */
%{
/* also store struct type so we can do a sizeof() later */
static char *ECPGstruct_sizeof = NULL;
+/* for forward declarations we have to store some data as well */
+static char *forward_name = NULL;
+
struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, NULL, {NULL}};
struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
enum ECPGttype type_enum;
enum ECPGdtype dtype_enum;
struct fetch_desc descriptor;
+ struct su_symbol struct_union;
}
/* special embedded SQL token */
%type <str> reserved_keyword unreserved_keyword ecpg_interval
%type <str> col_name_keyword func_name_keyword precision opt_scale
%type <str> ECPGTypeName variablelist ECPGColLabelCommon c_variable
-%type <str> s_struct_union_symbol inf_val_list inf_col_list
+%type <str> inf_val_list inf_col_list
+
+%type <struct_union> s_struct_union_symbol
%type <descriptor> ECPGGetDescriptor
}
| StringConst
{
- printf("MM: %s\n", $1);
if ($1[0] == '\"')
$$ = $1;
else if (strcmp($1, " ?") == 0) /* variable */
| s_struct_union_symbol
{
/* this is for named structs/unions */
- char *name = $1;
- struct typedefs *this = get_typedef(name);
-
- $$.type_str = mm_strdup(this->name);
- $$.type_enum = this->type->type_enum;
- $$.type_dimension = this->type->type_dimension;
- $$.type_index = this->type->type_index;
- $$.type_sizeof = this->type->type_sizeof;
- struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
- free(name);
+ char *name;
+ struct typedefs *this;
+ bool forward = (strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
+
+ name = cat2_str($1.su, $1.symbol);
+ /* Do we have a forward definition? */
+ if (!forward)
+ {
+ /* No */
+
+ this = get_typedef(name);
+ $$.type_str = mm_strdup(this->name);
+ $$.type_enum = this->type->type_enum;
+ $$.type_dimension = this->type->type_dimension;
+ $$.type_index = this->type->type_index;
+ $$.type_sizeof = this->type->type_sizeof;
+ struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
+ free(name);
+ }
+ else
+ {
+ $$.type_str = name;
+ $$.type_enum = ECPGt_long;
+ $$.type_dimension = make_str("-1");
+ $$.type_index = make_str("-1");
+ $$.type_sizeof = make_str("");
+ struct_member_list[struct_level] = NULL;
+ }
}
;
| s_struct_union_symbol
{
/* this is for named structs/unions */
- char *name = $1;
- struct typedefs *this = get_typedef(name);
- $$.type_str = mm_strdup(this->name);
- $$.type_enum = this->type->type_enum;
- $$.type_dimension = this->type->type_dimension;
- $$.type_index = this->type->type_index;
- $$.type_sizeof = this->type->type_sizeof;
- struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
- free(name);
+ char *name;
+ struct typedefs *this;
+ bool forward = (strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
+
+ name = cat2_str($1.su, $1.symbol);
+ /* Do we have a forward definition? */
+ if (!forward)
+ {
+ /* No */
+
+ this = get_typedef(name);
+ $$.type_str = mm_strdup(this->name);
+ $$.type_enum = this->type->type_enum;
+ $$.type_dimension = this->type->type_dimension;
+ $$.type_index = this->type->type_index;
+ $$.type_sizeof = this->type->type_sizeof;
+ struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
+ free(name);
+ }
+ else
+ {
+ $$.type_str = name;
+ $$.type_enum = ECPGt_long;
+ $$.type_dimension = make_str("-1");
+ $$.type_index = make_str("-1");
+ $$.type_sizeof = make_str("");
+ struct_member_list[struct_level] = NULL;
+ }
}
;
struct_member_list[struct_level++] = NULL;
if (struct_level >= STRUCT_DEPTH)
mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure/union definition");
+ forward_name = mm_strdup($1.symbol);
}
'{' variable_declarations '}'
{
ECPGfree_struct_member(struct_member_list[struct_level]);
struct_member_list[struct_level] = NULL;
free(actual_storage[struct_level--]);
- if (strncmp($1, "struct", sizeof("struct")-1) == 0)
+ if (strncmp($1.su, "struct", sizeof("struct")-1) == 0)
$$.type_enum = ECPGt_struct;
else
$$.type_enum = ECPGt_union;
- $$.type_str = mm_strdup($1);
- $$.type_sizeof = cat_str(4, $1, make_str("{"), $4, make_str("}"));
+ $$.type_str = cat2_str($1.su, $1.symbol);
+ $$.type_sizeof = cat_str(4, mm_strdup($$.type_str), make_str("{"), $4, make_str("}"));
+ free(forward_name);
+ forward_name = NULL;
}
;
s_struct_union_symbol: SQL_STRUCT symbol
{
- $$ = cat2_str(make_str("struct"), $2);
- ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), strdup($$), make_str(")"));
+ $$.su = make_str("struct");
+ $$.symbol = $2;
+ ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), make_str(")"));
}
| UNION symbol
{
- $$ = cat2_str(make_str("union"), $2);
+ $$.su = make_str("union");
+ $$.symbol = $2;
}
;
case ECPGt_array:
if (indicator_set && ind_type->type != ECPGt_array)
mmerror(INDICATOR_NOT_ARRAY, ET_FATAL, "Indicator for array/pointer has to be array/pointer.\n");
-
switch (type->u.element->type)
{
case ECPGt_array:
break;
case ECPGt_struct:
case ECPGt_union:
- /* If var_array_element is not equal * NULL, we have to use the * <var_array_element>th entry and not * the whole array */ if (var_array_element == NULL)
- ECPGdump_a_struct(o, name, ind_name, type->size,
+ /* If var_array_element is not equal
+ * NULL, we have to use the
+ * <var_array_element>th entry and
+ * not the whole array */
+ if (var_array_element == NULL)
+ ECPGdump_a_struct(o, name,
+ ind_name,
+ type->size,
type->u.element,
(ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element,
NULL, prefix, ind_prefix);
char *str;
};
+struct su_symbol
+{
+ char *su;
+ char *symbol;
+};
+
struct this_type
{
enum ECPGttype type_enum;
}
static struct variable *
-find_struct(char *name, char *next)
+find_struct(char *name, char *next, char *end)
{
struct variable *p;
char c = *next;
mmerror(PARSE_ERROR, ET_FATAL, errortext);
}
- /* restore the name, we will need it later on */
+ /* restore the name, we will need it later */
*next = c;
- next++;
- return find_struct_member(name, next, p->type->u.element->u.members, p->brace_level);
+ return find_struct_member(name, end, p->type->u.element->u.members, p->brace_level);
}
else
{
- if (p->type->type != ECPGt_struct && p->type->type != ECPGt_union)
+ if (next == end)
{
- snprintf(errortext, sizeof(errortext), "variable %s is neither a structure nor a union", name);
- mmerror(PARSE_ERROR, ET_FATAL, errortext);
+ if (p->type->type != ECPGt_struct && p->type->type != ECPGt_union)
+ {
+ snprintf(errortext, sizeof(errortext), "variable %s is neither a structure nor a union", name);
+ mmerror(PARSE_ERROR, ET_FATAL, errortext);
+ }
+
+ /* restore the name, we will need it later */
+ *next = c;
+
+ return find_struct_member(name, end, p->type->u.members, p->brace_level);
}
+ else
+ {
+ if (p->type->type != ECPGt_array)
+ {
+ snprintf(errortext, sizeof(errortext), "variable %s is not an array", name);
+ mmerror(PARSE_ERROR, ET_FATAL, errortext);
+ }
- /* restore the name, we will need it later on */
- *next = c;
+ if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union)
+ {
+ snprintf(errortext, sizeof(errortext), "variable %s is not a pointer to a structure or a union", name);
+ mmerror(PARSE_ERROR, ET_FATAL, errortext);
+ }
+
+ /* restore the name, we will need it later */
+ *next = c;
- return find_struct_member(name, next, p->type->u.members, p->brace_level);
+ return find_struct_member(name, end, p->type->u.element->u.members, p->brace_level);
+ }
}
}
struct variable *
find_variable(char *name)
{
- char *next;
+ char *next, *end;
struct variable *p;
+ int count;
- 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);
+ printf("MM: find %s\n", name);
+
+ next = strpbrk(name, ".[-");
+ if (next)
+ {
+ if (*next == '[')
+ {
+ /* We don't care about what's inside the array braces
+ * so just eat up the character */
+ for (count=1, end=next+1; count; end++)
+ {
+ switch (*end)
+ {
+ case '[': count++;
+ break;
+ case ']': count--;
+ break;
+ default : break;
+ }
+ }
+ if (*end == '.') p = find_struct(name, next, end);
+ else
+ {
+ char c = *next;
+
+ *next = '\0';
+ p = find_simple(name);
+ *next = c;
+ }
+ }
+ else p = find_struct(name, next, next);
+ }
+ else p = find_simple(name);
if (p == NULL)
{
mmerror(PARSE_ERROR, ET_FATAL, errortext);
/* mmerror(PARSE_ERROR, ET_FATAL, "No multilevel (more than 2) pointer supported %d",pointer_len);*/
}
+
if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char)
mmerror(PARSE_ERROR, ET_FATAL, "No pointer to pointer supported for this type");