Committed again to add the missing files/patches.
authorMichael Meskes
Fri, 16 Nov 2001 08:36:37 +0000 (08:36 +0000)
committerMichael Meskes
Fri, 16 Nov 2001 08:36:37 +0000 (08:36 +0000)
src/interfaces/ecpg/preproc/extern.h
src/interfaces/ecpg/preproc/preproc.y
src/interfaces/ecpg/preproc/variable.c
src/interfaces/ecpg/test/testdynalloc.pgc [new file with mode: 0644]

index 43f99c9cc71faf3f1b4273b6b5ca2b8af48a4b62..1fd27655db9a02c3bf279f8d6b7b146bba44d545 100644 (file)
@@ -71,7 +71,7 @@ extern void add_variable(struct arguments **, struct variable *, struct variable
 extern void append_variable(struct arguments **, struct variable *, struct variable *);
 extern void dump_variables(struct arguments *, int);
 extern struct typedefs *get_typedef(char *);
-extern void adjust_array(enum ECPGttype, int *, int *, int, int, bool);
+extern void adjust_array(enum ECPGttype, int *, int *, int, int, int);
 extern void reset_variables(void);
 extern void check_indicator(struct ECPGtype *);
 extern void remove_variables(int);
index edb8941de87d68d3a51ebc2e8fa6e443f0281f81..118a034693ba53435a8c70e19bd59243c22d9cd7 100644 (file)
@@ -279,7 +279,7 @@ make_name(void)
 %type      key_match ColLabel SpecialRuleRelation ColId columnDef
 %type      ColConstraint ColConstraintElem drop_type Bitconst
 %type      OptTableElementList OptTableElement TableConstraint
-%type      ConstraintElem key_actions ColQualList type_name DropSchemaStmt
+%type      ConstraintElem key_actions ColQualList TypeFuncId DropSchemaStmt
 %type      target_list target_el update_target_list alias_clause
 %type      update_target_el opt_id relation_name database_name
 %type      access_method attr_name class index_name name func_name
@@ -357,9 +357,7 @@ make_name(void)
 %type      struct_type s_struct declaration declarations variable_declarations
 %type      s_union union_type ECPGSetAutocommit on_off
 %type     ECPGAllocateDescr ECPGDeallocateDescr symbol opt_symbol
-%type     ECPGGetDescriptorHeader ECPGColLabel
-%type     reserved_keyword unreserved_keyword
-%type     col_name_keyword func_name_keyword
+%type     ECPGGetDescriptorHeader ECPGTypeFuncId ECPGColId ECPGColLabel
 %type     ECPGTypeName variablelist cvariable
 
 %type   ECPGGetDescriptor
@@ -1966,7 +1964,7 @@ func_type:    Typename
                {
                    $$ = $1;
                }
-       | type_name '.' ColId '%' TYPE_P   
+       | TypeFuncId '.' ColId '%' TYPE_P   
                {
                    $$ = cat_str(4, $1, make_str("."), $3, make_str("% type"));
                }
@@ -2980,7 +2978,8 @@ ConstTypename:  Generic   { $$ = $1; }
        | Character { $$ = $1; }
        ;
 
-Generic:  type_name                { $$ = $1; }
+Generic:  TypeFuncId           { $$ = $1; }
+       | ECPGTypeName          { $$ = $1; }
        ;
 
 /* SQL92 numeric data types
@@ -4429,6 +4428,7 @@ opt_initializer: /* empty */      { $$ = EMPTY; }
 
 opt_pointer: /* empty */   { $$ = EMPTY; }
    | '*'           { $$ = make_str("*"); }
+   | '*' '*'       { $$ = make_str("**"); }
    ;
 
 /*
@@ -4672,7 +4672,7 @@ ECPGTypedef: TYPE_P ColLabel IS type opt_type_array_bounds opt_reference
                    }
        }
 
-       adjust_array($4.type_enum, &dimension, &length, $4.type_dimension, $4.type_index, strlen($6));
+       adjust_array($4.type_enum, &dimension, &length, $4.type_dimension, $4.type_index, *$6?1:0);
 
            this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
 
@@ -4755,7 +4755,7 @@ ECPGVar: SQL_VAR ColLabel IS type opt_type_array_bounds opt_reference
            initializer == 1)
            mmerror(ET_ERROR, "Initializer not allowed in EXEC SQL VAR command");
 
-       adjust_array($4.type_enum, &dimension, &length, $4.type_dimension, $4.type_index, strlen($6));
+       adjust_array($4.type_enum, &dimension, &length, $4.type_dimension, $4.type_index, *$6?1:0);
 
        switch ($4.type_enum)
        {
@@ -4875,48 +4875,48 @@ action : SQL_CONTINUE
 
 /* some other stuff for ecpg */
 
-/* additional unreserved keywords */
-ECPGKeywords:  SQL_BREAK       { $$ = make_str("break"); }
-       | SQL_CALL              { $$ = make_str("call"); }
-       | SQL_CARDINALITY       { $$ = make_str("cardinality"); }
+/* additional ColId entries */
+ECPGKeywords:    SQL_BREAK         { $$ = make_str("break"); }
+       | SQL_CALL          { $$ = make_str("call"); }
+       | SQL_CARDINALITY   { $$ = make_str("cardinality"); }
        | SQL_CONNECT           { $$ = make_str("connect"); }
        | SQL_CONTINUE          { $$ = make_str("continue"); }
-       | SQL_COUNT             { $$ = make_str("count"); }
-       | SQL_DATA              { $$ = make_str("data"); }
+       | SQL_COUNT         { $$ = make_str("count"); }
+       | SQL_DATA          { $$ = make_str("data"); }
        | SQL_DATETIME_INTERVAL_CODE    { $$ = make_str("datetime_interval_code"); }
        | SQL_DATETIME_INTERVAL_PRECISION   { $$ = make_str("datetime_interval_precision"); }
        | SQL_DEALLOCATE        { $$ = make_str("deallocate"); }
        | SQL_DISCONNECT        { $$ = make_str("disconnect"); }
-       | SQL_FOUND             { $$ = make_str("found"); }
-       | SQL_GO                { $$ = make_str("go"); }
-       | SQL_GOTO              { $$ = make_str("goto"); }
+       | SQL_FOUND         { $$ = make_str("found"); }
+       | SQL_GO            { $$ = make_str("go"); }
+       | SQL_GOTO          { $$ = make_str("goto"); }
        | SQL_IDENTIFIED        { $$ = make_str("identified"); }
        | SQL_INDICATOR         { $$ = make_str("indicator"); }
        | SQL_KEY_MEMBER        { $$ = make_str("key_member"); }
        | SQL_LENGTH            { $$ = make_str("length"); }
-       | SQL_NAME              { $$ = make_str("name"); }
+       | SQL_NAME          { $$ = make_str("name"); }
        | SQL_NULLABLE          { $$ = make_str("nullable"); }
        | SQL_OCTET_LENGTH      { $$ = make_str("octet_length"); }
-       | SQL_OPEN              { $$ = make_str("open"); }
+       | SQL_OPEN          { $$ = make_str("open"); }
        | SQL_PREPARE           { $$ = make_str("prepare"); }
        | SQL_RELEASE           { $$ = make_str("release"); }
        | SQL_RETURNED_LENGTH       { $$ = make_str("returned_length"); }
        | SQL_RETURNED_OCTET_LENGTH { $$ = make_str("returned_octet_length"); }
-       | SQL_SCALE             { $$ = make_str("scale"); }
+       | SQL_SCALE         { $$ = make_str("scale"); }
        | SQL_SECTION           { $$ = make_str("section"); }
        | SQL_SQLERROR          { $$ = make_str("sqlerror"); }
        | SQL_SQLPRINT          { $$ = make_str("sqlprint"); }
        | SQL_SQLWARNING        { $$ = make_str("sqlwarning"); }
-       | SQL_STOP              { $$ = make_str("stop"); }
-       | SQL_VAR               { $$ = make_str("var"); }
+       | SQL_STOP          { $$ = make_str("stop"); }
+       | SQL_VAR           { $$ = make_str("var"); }
        | SQL_WHENEVER          { $$ = make_str("whenever"); }
+/*     | ECPGTypeName          { $$ = $1 }*/
        ;
 
-/* additional keywords that can be SQL type names (but not ECPGColLabels) */
-ECPGTypeName:  SQL_BOOL        { $$ = make_str("bool"); }
-       | SQL_INT           { $$ = make_str("int"); }
-       | SQL_LONG          { $$ = make_str("long"); }
-       | SQL_SHORT         { $$ = make_str("short"); }
+ECPGTypeName:    SQL_BOOL      { $$ = make_str("bool"); }
+       | SQL_INT       { $$ = make_str("int"); }
+       | SQL_LONG      { $$ = make_str("long"); }
+       | SQL_SHORT     { $$ = make_str("short"); }
        | SQL_STRUCT        { $$ = make_str("struct"); }
        | SQL_SIGNED        { $$ = make_str("signed"); }
        | SQL_UNSIGNED      { $$ = make_str("unsigned"); }
@@ -4929,72 +4929,25 @@ opt_symbol: symbol      { $$ = $1; }
 symbol:        ColLabel    { $$ = $1; };
 
 /*
- * Name classification hierarchy.
- *
- * IDENT is the lexeme returned by the lexer for identifiers that match
- * no known keyword.  In most cases, we can accept certain keywords as
- * names, not only IDENTs.  We prefer to accept as many such keywords
- * as possible to minimize the impact of "reserved words" on programmers.
- * So, we divide names into several possible classes.  The classification
- * is chosen in part to make keywords acceptable as names wherever possible.
- */
-
-/* Column identifier --- names that can be column, table, etc names.
- */
-ColId:  ident                          { $$ = $1; }
-       | unreserved_keyword            { $$ = $1; }
-       | col_name_keyword              { $$ = $1; }
-       | ECPGKeywords                  { $$ = $1; }
-       | CHAR                          { $$ = make_str("char"); }
-       ;
-
-/* Type identifier --- names that can be type names.
- */
-type_name:  ident                      { $$ = $1; }
-       | unreserved_keyword            { $$ = $1; }
-       | ECPGKeywords                  { $$ = $1; }
-       | ECPGTypeName                  { $$ = $1; }
-       ;
-
-/* Function identifier --- names that can be function names.
+ * Keyword classification lists.  Generally, every keyword present in
+ * the Postgres grammar should be in one of these lists.  (Presently,
+ * "AS" is the sole exception: it is our only completely-reserved word.)
+ *
+ * Put a new keyword into the earliest list (of TypeFuncId, ColId, ColLabel)
+ * that it can go into without creating shift or reduce conflicts.  The
+ * earlier lists define "less reserved" categories of keywords.  Notice that
+ * each list includes by reference the ones before it.
  */
-func_name:  ident                      { $$ = $1; }
-       | unreserved_keyword            { $$ = $1; }
-       | func_name_keyword             { $$ = $1; }
-       | ECPGKeywords                  { $$ = $1; }
-       ;
 
-/* Column label --- allowed labels in "AS" clauses.
- * This presently includes *all* Postgres keywords.
+/* Type/func identifier --- names that can be type and function names
+ * (as well as ColIds --- ie, these are completely unreserved keywords).
  */
-ColLabel:  ECPGColLabel                    { $$ = $1; }
-       | ECPGTypeName                  { $$ = $1; }
-       | CHAR                          { $$ = make_str("char"); }
-       | UNION                         { $$ = make_str("union"); }
-       ;
-
-ECPGColLabel:  ident                   { $$ = $1; }
-       | unreserved_keyword            { $$ = $1; }
-       | col_name_keyword              { $$ = $1; }
-       | func_name_keyword             { $$ = $1; }
-       | reserved_keyword              { $$ = $1; }
+TypeFuncId:  ECPGTypeFuncId                { $$ = $1; }
        | ECPGKeywords                  { $$ = $1; }
        ;
 
-
-/*
- * Keyword classification lists.  Generally, every keyword present in
- * the Postgres grammar should appear in exactly one of these lists.
- *
- * Put a new keyword into the first list that it can go into without causing
- * shift or reduce conflicts.  The earlier lists define "less reserved"
- * categories of keywords.
- */
-
-/* "Unreserved" keywords --- available for use as any kind of name.
- */
-unreserved_keyword:
-         ABORT_TRANS                   { $$ = make_str("abort"); }
+ECPGTypeFuncId:  ident                 { $$ = $1; }
+       | ABORT_TRANS                   { $$ = make_str("abort"); }
        | ABSOLUTE                      { $$ = make_str("absolute"); }
        | ACCESS                        { $$ = make_str("access"); }
        | ACTION                        { $$ = make_str("action"); }
@@ -5150,96 +5103,69 @@ unreserved_keyword:
        | ZONE                          { $$ = make_str("zone"); }
        ;
 
-/* Column identifier --- keywords that can be column, table, etc names.
+/* Column identifier --- names that can be column, table, etc names.
  *
- * Many of these keywords will in fact be recognized as type or function
- * names too; but they have special productions for the purpose, and so
- * can't be treated as "generic" type or function names.
+ * This contains the TypeFuncId list plus those keywords that conflict
+ * only with typename productions, not with other uses.  Note that
+ * most of these keywords will in fact be recognized as type names too;
+ * they just have to have special productions for the purpose.
  *
- * The type names appearing here are not usable as function names
- * because they can be followed by '(' in typename productions, which
- * looks too much like a function call for aLR(1) parser.
+ * Most of these cannot be in TypeFuncId (ie, are not also usable as function
+ * names) because they can be followed by '(' in typename productions, which
+ * looks too much like a function call for a LALR(1) parser.
  */
-col_name_keyword:
-         BIT                           { $$ = make_str("bit"); }
+ColId:  ECPGColId                      { $$ = $1; }
+       | CHAR                          { $$ = make_str("char"); }
+       ;
+
+ECPGColId:  TypeFuncId                 { $$ = $1; }
+       | BIT                           { $$ = make_str("bit"); }
 /* CHAR must be excluded from ECPGColLabel because of conflict with UNSIGNED
        | CHAR                          { $$ = make_str("char"); }
  */
        | CHARACTER                     { $$ = make_str("character"); }
-       | COALESCE                      { $$ = make_str("coalesce"); }
        | DEC                           { $$ = make_str("dec"); }
        | DECIMAL                       { $$ = make_str("decimal"); }
-       | EXISTS                        { $$ = make_str("exists"); }
-       | EXTRACT                       { $$ = make_str("extract"); }
        | FLOAT                         { $$ = make_str("float"); }
        | INTERVAL                      { $$ = make_str("interval"); }
        | NCHAR                         { $$ = make_str("nchar"); }
        | NONE                          { $$ = make_str("none"); }
-       | NULLIF                        { $$ = make_str("nullif"); }
        | NUMERIC                       { $$ = make_str("numeric"); }
-       | POSITION                      { $$ = make_str("position"); }
        | SETOF                         { $$ = make_str("setof"); }
-       | SUBSTRING                     { $$ = make_str("substring"); }
        | TIME                          { $$ = make_str("time"); }
        | TIMESTAMP                     { $$ = make_str("timestamp"); }
-       | TRIM                          { $$ = make_str("trim"); }
        | VARCHAR                       { $$ = make_str("varchar"); }
        ;
 
-/* Function identifier --- keywords that can be function names.
- *
- * Most of these are keywords that are used as operators in expressions;
- * in general such keywords can't be column names because they would be
- * ambiguous with variables, but they are unambiguous as function identifiers.
+/* Column label --- allowed labels in "AS" clauses.
  *
- * Do not include POSITION, SUBSTRING, etc here since they have explicit
- * productions in a_expr to support the goofy SQL9x argument syntax.
- *  - thomas 2000-11-28
+ * Keywords appear here if they could not be distinguished from variable,
+ * type, or function names in some contexts.
+ * When adding a ColLabel, consider whether it can be added to func_name.
  */
-func_name_keyword:
-         BETWEEN                       { $$ = make_str("between"); }
-       | BINARY                        { $$ = make_str("binary"); }
-       | CROSS                         { $$ = make_str("cross"); }
-       | FREEZE                        { $$ = make_str("freeze"); }
-       | FULL                          { $$ = make_str("full"); }
-       | ILIKE                         { $$ = make_str("ilike"); }
-       | IN                            { $$ = make_str("in"); }
-       | INNER_P                       { $$ = make_str("inner"); }
-       | IS                            { $$ = make_str("is"); }
-       | ISNULL                        { $$ = make_str("isnull"); }
-       | JOIN                          { $$ = make_str("join"); }
-       | LEFT                          { $$ = make_str("left"); }
-       | LIKE                          { $$ = make_str("like"); }
-       | NATURAL                       { $$ = make_str("natural"); }
-       | NOTNULL                       { $$ = make_str("notnull"); }
-       | OUTER_P                       { $$ = make_str("outer"); }
-       | OVERLAPS                      { $$ = make_str("overlaps"); }
-       | PUBLIC                        { $$ = make_str("public"); }
-       | RIGHT                         { $$ = make_str("right"); }
-       | VERBOSE                       { $$ = make_str("verbose"); }
+ColLabel:  ECPGColLabel                    { $$ = $1; }
+       | CHAR                          { $$ = make_str("char"); }
+       | UNION                         { $$ = make_str("union"); }
        ;
 
-/* Reserved keyword --- these keywords are usable only as a ColLabel.
- *
- * Keywords appear here if they could not be distinguished from variable,
- * type, or function names in some contexts.  Don't put things here unless
- * forced to.
- */
-reserved_keyword:
-         ALL                           { $$ = make_str("all"); }
+ECPGColLabel:  ECPGColId               { $$ = $1; }
+       | ALL                           { $$ = make_str("all"); }
        | ANALYSE                       { $$ = make_str("analyse"); } /* British */
        | ANALYZE                       { $$ = make_str("analyze"); }
        | AND                           { $$ = make_str("and"); }
        | ANY                           { $$ = make_str("any"); }
-       | AS                            { $$ = make_str("as"); }
        | ASC                           { $$ = make_str("asc"); }
+       | BETWEEN                       { $$ = make_str("between"); }
+       | BINARY                        { $$ = make_str("binary"); }
        | BOTH                          { $$ = make_str("both"); }
        | CASE                          { $$ = make_str("case"); }
        | CAST                          { $$ = make_str("cast"); }
        | CHECK                         { $$ = make_str("check"); }
+       | COALESCE                      { $$ = make_str("coalesce"); }
        | COLLATE                       { $$ = make_str("collate"); }
        | COLUMN                        { $$ = make_str("column"); }
        | CONSTRAINT                    { $$ = make_str("constraint"); }
+       | CROSS                         { $$ = make_str("cross"); }
        | CURRENT_DATE                  { $$ = make_str("current_date"); }
        | CURRENT_TIME                  { $$ = make_str("current_time"); }
        | CURRENT_TIMESTAMP             { $$ = make_str("current_timestamp"); }
@@ -5252,19 +5178,34 @@ reserved_keyword:
        | ELSE                          { $$ = make_str("else"); }
        | END_TRANS                     { $$ = make_str("end"); }
        | EXCEPT                        { $$ = make_str("except"); }
+       | EXISTS                        { $$ = make_str("exists"); }
+       | EXTRACT                       { $$ = make_str("extract"); }
        | FALSE_P                       { $$ = make_str("false"); }
        | FOR                           { $$ = make_str("for"); }
        | FOREIGN                       { $$ = make_str("foreign"); }
+       | FREEZE                        { $$ = make_str("freeze"); }
        | FROM                          { $$ = make_str("from"); }
+       | FULL                          { $$ = make_str("full"); }
        | GROUP                         { $$ = make_str("group"); }
        | HAVING                        { $$ = make_str("having"); }
+       | ILIKE                         { $$ = make_str("ilike"); }
+       | IN                            { $$ = make_str("in"); }
        | INITIALLY                     { $$ = make_str("initially"); }
+       | INNER_P                       { $$ = make_str("inner"); }
        | INTERSECT                     { $$ = make_str("intersect"); }
        | INTO                          { $$ = make_str("into"); }
+       | IS                            { $$ = make_str("is"); }
+       | ISNULL                        { $$ = make_str("isnull"); }
+       | JOIN                          { $$ = make_str("join"); }
        | LEADING                       { $$ = make_str("leading"); }
+       | LEFT                          { $$ = make_str("left"); }
+       | LIKE                          { $$ = make_str("like"); }
        | LIMIT                         { $$ = make_str("limit"); }
+       | NATURAL                       { $$ = make_str("natural"); }
        | NEW                           { $$ = make_str("new"); }
        | NOT                           { $$ = make_str("not"); }
+       | NOTNULL                       { $$ = make_str("notnull"); }
+       | NULLIF                        { $$ = make_str("nullif"); }
        | NULL_P                        { $$ = make_str("null"); }
        | OFF                           { $$ = make_str("off"); }
        | OFFSET                        { $$ = make_str("offset"); }
@@ -5273,15 +5214,22 @@ reserved_keyword:
        | ONLY                          { $$ = make_str("only"); }
        | OR                            { $$ = make_str("or"); }
        | ORDER                         { $$ = make_str("order"); }
+       | OUTER_P                       { $$ = make_str("outer"); }
+       | OVERLAPS                      { $$ = make_str("overlaps"); }
+       | POSITION                      { $$ = make_str("position"); }
        | PRIMARY                       { $$ = make_str("primary"); }
+       | PUBLIC                        { $$ = make_str("public"); }
        | REFERENCES                    { $$ = make_str("references"); }
+       | RIGHT                         { $$ = make_str("right"); }
        | SELECT                        { $$ = make_str("select"); }
        | SESSION_USER                  { $$ = make_str("session_user"); }
        | SOME                          { $$ = make_str("some"); }
+       | SUBSTRING                     { $$ = make_str("substring"); }
        | TABLE                         { $$ = make_str("table"); }
        | THEN                          { $$ = make_str("then"); }
        | TO                            { $$ = make_str("to"); }
        | TRAILING                      { $$ = make_str("trailing"); }
+       | TRIM                          { $$ = make_str("trim"); }
        | TRUE_P                        { $$ = make_str("true"); }
 /* UNION must be excluded from ECPGColLabel because of conflict with s_union
        | UNION                         { $$ = make_str("union"); }
@@ -5289,10 +5237,44 @@ reserved_keyword:
        | UNIQUE                        { $$ = make_str("unique"); }
        | USER                          { $$ = make_str("user"); }
        | USING                         { $$ = make_str("using"); }
+       | VERBOSE                       { $$ = make_str("verbose"); }
        | WHEN                          { $$ = make_str("when"); }
        | WHERE                         { $$ = make_str("where"); }
        ;
 
+/* Function identifier --- names that can be function names.
+ *
+ * This contains the TypeFuncId list plus some ColLabel keywords
+ * that are used as operators in expressions; in general such keywords
+ * can't be ColId because they would be ambiguous with variable names,
+ * but they are unambiguous as function identifiers.
+ *
+ * Do not include POSITION, SUBSTRING, etc here since they have explicit
+ * productions in a_expr to support the goofy SQL9x argument syntax.
+ *  - thomas 2000-11-28
+ */
+func_name:  TypeFuncId                 { $$ = $1; }
+       | BETWEEN                       { $$ = make_str("between"); }
+       | BINARY                        { $$ = make_str("binary"); }
+       | CROSS                         { $$ = make_str("cross"); }
+       | FREEZE                        { $$ = make_str("freeze"); }
+       | FULL                          { $$ = make_str("full"); }
+       | ILIKE                         { $$ = make_str("ilike"); }
+       | IN                            { $$ = make_str("in"); }
+       | INNER_P                       { $$ = make_str("inner"); }
+       | IS                            { $$ = make_str("is"); }
+       | ISNULL                        { $$ = make_str("isnull"); }
+       | JOIN                          { $$ = make_str("join"); }
+       | LEFT                          { $$ = make_str("left"); }
+       | LIKE                          { $$ = make_str("like"); }
+       | NATURAL                       { $$ = make_str("natural"); }
+       | NOTNULL                       { $$ = make_str("notnull"); }
+       | OUTER_P                       { $$ = make_str("outer"); }
+       | OVERLAPS                      { $$ = make_str("overlaps"); }
+       | PUBLIC                        { $$ = make_str("public"); }
+       | RIGHT                         { $$ = make_str("right"); }
+       | VERBOSE                       { $$ = make_str("verbose"); }
+       ;
 
 into_list : coutputvariable | into_list ',' coutputvariable;
 
index 0c5749b7891e0c32bb63063e6b3aa73795c30fbc..b39c0e60ef41a607b80b71b22f6e7f6cb25793bf 100644 (file)
@@ -298,7 +298,7 @@ get_typedef(char *name)
 }
 
 void
-adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dimension, int type_index, bool pointer)
+adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dimension, int type_index, int pointer_len)
 {
    if (type_index >= 0)
    {
@@ -318,8 +318,19 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
 
        *dimension = type_dimension;
    }
+   
+   if (pointer_len>2)
+   {   sprintf(errortext, "No multilevel (more than 2) pointer supported %d",pointer_len);
+       mmerror(ET_FATAL, errortext);
+//     mmerror(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(ET_FATAL, "No pointer to pointer supported for this type");
+
+   if (pointer_len>1 && (*length >= 0 || *dimension >= 0))
+       mmerror(ET_FATAL, "No multi-dimensional array support");
 
-   if (*length >= 0 && *dimension >= 0 && pointer)
+   if (*length >= 0 && *dimension >= 0 && pointer_len)
        mmerror(ET_FATAL, "No multi-dimensional array support");
 
    switch (type_enum)
@@ -327,7 +338,7 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
        case ECPGt_struct:
        case ECPGt_union:
            /* pointer has to get dimension 0 */
-           if (pointer)
+           if (pointer_len)
            {
                *length = *dimension;
                *dimension = 0;
@@ -339,7 +350,7 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
            break;
        case ECPGt_varchar:
            /* pointer has to get dimension 0 */
-           if (pointer)
+           if (pointer_len)
                *dimension = 0;
 
            /* one index is the string length */
@@ -352,8 +363,15 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
            break;
        case ECPGt_char:
        case ECPGt_unsigned_char:
+           /* char ** */
+           if (pointer_len==2)
+           {
+               *length = *dimension = 0;
+               break;
+           }
+           
            /* pointer has to get length 0 */
-           if (pointer)
+           if (pointer_len==1)
                *length = 0;
 
            /* one index is the string length */
@@ -362,11 +380,10 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim
                *length = (*dimension < 0) ? 1 : *dimension;
                *dimension = -1;
            }
-
            break;
        default:
            /* a pointer has dimension = 0 */
-           if (pointer)
+           if (pointer_len)
            {
                *length = *dimension;
                *dimension = 0;
diff --git a/src/interfaces/ecpg/test/testdynalloc.pgc b/src/interfaces/ecpg/test/testdynalloc.pgc
new file mode 100644 (file)
index 0000000..c0023f8
--- /dev/null
@@ -0,0 +1,33 @@
+#include 
+exec sql include sqlca;
+#include 
+
+int main()
+{  
+   exec sql begin declare section;
+   char **cpp=0;
+   int *ipointer=0;
+   exec sql end declare section;
+   int i;
+
+   if (getenv("SQLOPT")) ECPGdebug(1,stderr);
+
+   exec sql whenever sqlerror do sqlprint();
+   exec sql connect to template1;
+   
+   exec sql allocate descriptor mydesc;
+   exec sql select tablename into descriptor mydesc from pg_tables;
+   exec sql get descriptor mydesc value 1 :cpp=DATA, :ipointer=INDICATOR;
+
+   printf("Result ");
+   for (i=0;i
+   {  if (ipointer[i]) printf("NULL, ");
+      else printf("'%s', ",cpp[i]); 
+   }
+   ECPGfree_auto_mem();
+   printf("\n");
+
+   exec sql deallocate descriptor mydesc;
+   exec sql disconnect;
+   return 0;
+}