LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/preproc - variable.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 329 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 16 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* src/interfaces/ecpg/preproc/variable.c */
       2              : 
       3              : #include "postgres_fe.h"
       4              : 
       5              : #include "preproc_extern.h"
       6              : 
       7              : static struct variable *allvariables = NULL;
       8              : 
       9              : /* this probably belongs in util.c, but for now it's only needed here */
      10              : static char *
      11            0 : loc_nstrdup(const char *in, size_t len)
      12              : {
      13            0 :         char       *out;
      14              : 
      15            0 :         out = loc_alloc(len + 1);
      16            0 :         memcpy(out, in, len);
      17            0 :         out[len] = '\0';
      18              : 
      19            0 :         return out;
      20            0 : }
      21              : 
      22              : struct variable *
      23            0 : new_variable(const char *name, struct ECPGtype *type, int brace_level)
      24              : {
      25            0 :         struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable));
      26              : 
      27            0 :         p->name = mm_strdup(name);
      28            0 :         p->type = type;
      29            0 :         p->brace_level = brace_level;
      30              : 
      31            0 :         p->next = allvariables;
      32            0 :         allvariables = p;
      33              : 
      34            0 :         return p;
      35            0 : }
      36              : 
      37              : /*
      38              :  * Perform lookup of a field within a struct
      39              :  *
      40              :  * 'name' is the entire C variable name
      41              :  * 'str' points just before the next field name to parse
      42              :  * 'members' and 'brace_level' describe the struct we are looking into
      43              :  *
      44              :  * Returns NULL if field is not found.
      45              :  *
      46              :  * This recurses if needed to handle sub-fields.
      47              :  */
      48              : static struct variable *
      49            0 : find_struct_member(const char *name, const char *str,
      50              :                                    struct ECPGstruct_member *members, int brace_level)
      51              : {
      52              :         /* ++ here skips over the '.', or the '>' of '->' */
      53            0 :         const char *next = strpbrk(++str, ".-["),
      54              :                            *end,
      55              :                            *field;
      56              : 
      57            0 :         if (next != NULL)
      58            0 :                 field = loc_nstrdup(str, next - str);
      59              :         else
      60            0 :                 field = str;
      61              : 
      62            0 :         for (; members; members = members->next)
      63              :         {
      64            0 :                 if (strcmp(members->name, field) == 0)
      65              :                 {
      66            0 :                         if (next == NULL)
      67              :                         {
      68              :                                 /* found the end */
      69            0 :                                 switch (members->type->type)
      70              :                                 {
      71              :                                         case ECPGt_array:
      72            0 :                                                 return new_variable(name, ECPGmake_array_type(ECPGmake_simple_type(members->type->u.element->type, members->type->u.element->size, members->type->u.element->counter), members->type->size), brace_level);
      73              :                                         case ECPGt_struct:
      74              :                                         case ECPGt_union:
      75            0 :                                                 return new_variable(name, ECPGmake_struct_type(members->type->u.members, members->type->type, members->type->type_name, members->type->struct_sizeof), brace_level);
      76              :                                         default:
      77            0 :                                                 return new_variable(name, ECPGmake_simple_type(members->type->type, members->type->size, members->type->counter), brace_level);
      78              :                                 }
      79              :                         }
      80              :                         else
      81              :                         {
      82            0 :                                 if (*next == '[')
      83              :                                 {
      84            0 :                                         int                     count;
      85              : 
      86              :                                         /*
      87              :                                          * We don't care about what's inside the array brackets so
      88              :                                          * just scan to find the matching right bracket.
      89              :                                          */
      90            0 :                                         for (count = 1, end = next + 1; count; end++)
      91              :                                         {
      92            0 :                                                 switch (*end)
      93              :                                                 {
      94              :                                                         case '[':
      95            0 :                                                                 count++;
      96            0 :                                                                 break;
      97              :                                                         case ']':
      98            0 :                                                                 count--;
      99            0 :                                                                 break;
     100              :                                                         default:
     101            0 :                                                                 break;
     102              :                                                 }
     103            0 :                                         }
     104            0 :                                 }
     105              :                                 else
     106            0 :                                         end = next;
     107              : 
     108            0 :                                 switch (*end)
     109              :                                 {
     110              :                                         case '\0':      /* found the end, but this time it has to be
     111              :                                                                  * an array element */
     112            0 :                                                 if (members->type->type != ECPGt_array)
     113            0 :                                                         mmfatal(PARSE_ERROR, "incorrectly formed variable \"%s\"", name);
     114              : 
     115            0 :                                                 switch (members->type->u.element->type)
     116              :                                                 {
     117              :                                                         case ECPGt_array:
     118            0 :                                                                 return new_variable(name, ECPGmake_array_type(ECPGmake_simple_type(members->type->u.element->u.element->type, members->type->u.element->u.element->size, members->type->u.element->u.element->counter), members->type->u.element->size), brace_level);
     119              :                                                         case ECPGt_struct:
     120              :                                                         case ECPGt_union:
     121            0 :                                                                 return new_variable(name, ECPGmake_struct_type(members->type->u.element->u.members, members->type->u.element->type, members->type->u.element->type_name, members->type->u.element->struct_sizeof), brace_level);
     122              :                                                         default:
     123            0 :                                                                 return new_variable(name, ECPGmake_simple_type(members->type->u.element->type, members->type->u.element->size, members->type->u.element->counter), brace_level);
     124              :                                                 }
     125              :                                                 break;
     126              :                                         case '-':
     127            0 :                                                 if (members->type->type == ECPGt_array)
     128            0 :                                                         return find_struct_member(name, ++end, members->type->u.element->u.members, brace_level);
     129              :                                                 else
     130            0 :                                                         return find_struct_member(name, ++end, members->type->u.members, brace_level);
     131              :                                                 break;
     132              :                                         case '.':
     133            0 :                                                 if (members->type->type == ECPGt_array)
     134            0 :                                                         return find_struct_member(name, end, members->type->u.element->u.members, brace_level);
     135              :                                                 else
     136            0 :                                                         return find_struct_member(name, end, members->type->u.members, brace_level);
     137              :                                                 break;
     138              :                                         default:
     139            0 :                                                 mmfatal(PARSE_ERROR, "incorrectly formed variable \"%s\"", name);
     140              :                                                 break;
     141              :                                 }
     142              :                         }
     143              :                 }
     144            0 :         }
     145              : 
     146            0 :         return NULL;
     147            0 : }
     148              : 
     149              : /*
     150              :  * Do struct lookup when we have found var.field, var->field, or var[n].field
     151              :  *
     152              :  * 'name' is the entire C variable name
     153              :  * 'next' points at the character after the base name
     154              :  * 'end' points at the character after the subscript, if there was a
     155              :  * subscript, else it's the same as 'next'.
     156              :  *
     157              :  * This is used only at the first level of field reference; sub-fields will
     158              :  * be handled by internal recursion in find_struct_member.
     159              :  */
     160              : static struct variable *
     161            0 : find_struct(const char *name, const char *next, const char *end)
     162              : {
     163            0 :         char       *prefix;
     164            0 :         struct variable *p;
     165              : 
     166              :         /* first get the mother structure entry */
     167            0 :         prefix = loc_nstrdup(name, next - name);
     168            0 :         p = find_variable(prefix);
     169              : 
     170            0 :         if (*next == '-')
     171              :         {
     172              :                 /* We have var->field */
     173            0 :                 if (p->type->type != ECPGt_array)
     174            0 :                         mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer", prefix);
     175              : 
     176            0 :                 if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union)
     177            0 :                         mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer to a structure or a union", prefix);
     178              : 
     179            0 :                 return find_struct_member(name, ++end, p->type->u.element->u.members, p->brace_level);
     180              :         }
     181              :         else
     182              :         {
     183            0 :                 if (next == end)
     184              :                 {
     185              :                         /* We have var.field */
     186            0 :                         if (p->type->type != ECPGt_struct && p->type->type != ECPGt_union)
     187            0 :                                 mmfatal(PARSE_ERROR, "variable \"%s\" is neither a structure nor a union", prefix);
     188              : 
     189            0 :                         return find_struct_member(name, end, p->type->u.members, p->brace_level);
     190              :                 }
     191              :                 else
     192              :                 {
     193              :                         /* We have var[n].field */
     194            0 :                         if (p->type->type != ECPGt_array)
     195            0 :                                 mmfatal(PARSE_ERROR, "variable \"%s\" is not an array", prefix);
     196              : 
     197            0 :                         if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union)
     198            0 :                                 mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer to a structure or a union", prefix);
     199              : 
     200            0 :                         return find_struct_member(name, end, p->type->u.element->u.members, p->brace_level);
     201              :                 }
     202              :         }
     203            0 : }
     204              : 
     205              : /* Look up a variable given its base name */
     206              : static struct variable *
     207            0 : find_simple(const char *name)
     208              : {
     209            0 :         struct variable *p;
     210              : 
     211            0 :         for (p = allvariables; p; p = p->next)
     212              :         {
     213            0 :                 if (strcmp(p->name, name) == 0)
     214            0 :                         return p;
     215            0 :         }
     216              : 
     217            0 :         return NULL;
     218            0 : }
     219              : 
     220              : /*
     221              :  * Build a "struct variable" for a C variable reference.
     222              :  *
     223              :  * The given "name" string is a CVARIABLE per pgc.l, so it can include not
     224              :  * only a base variable name but also ".field", "->field", or "[subscript]"
     225              :  * decoration.  We don't need to understand that fully, because we always
     226              :  * duplicate the whole string into the name field of the result variable
     227              :  * and emit it literally to the output file; the C compiler will make sense
     228              :  * of it later.  What we do need to do here is identify the type of the
     229              :  * target field or array element so that we can attach a correct ECPGtype
     230              :  * struct to the result.
     231              :  *
     232              :  * Note that this function will end the program in case of an unknown variable.
     233              :  */
     234              : struct variable *
     235            0 : find_variable(const char *name)
     236              : {
     237            0 :         const char *next,
     238              :                            *end;
     239            0 :         struct variable *p;
     240            0 :         int                     count;
     241              : 
     242            0 :         next = strpbrk(name, ".[-");
     243            0 :         if (next)
     244              :         {
     245              :                 /* Deal with field/subscript decoration */
     246            0 :                 if (*next == '[')
     247              :                 {
     248              :                         /*
     249              :                          * We don't care about what's inside the array brackets so just
     250              :                          * scan to find the matching right bracket.
     251              :                          */
     252            0 :                         for (count = 1, end = next + 1; count; end++)
     253              :                         {
     254            0 :                                 switch (*end)
     255              :                                 {
     256              :                                         case '[':
     257            0 :                                                 count++;
     258            0 :                                                 break;
     259              :                                         case ']':
     260            0 :                                                 count--;
     261            0 :                                                 break;
     262              :                                         case '\0':
     263            0 :                                                 mmfatal(PARSE_ERROR, "unmatched bracket in variable \"%s\"", name);
     264              :                                                 break;
     265              :                                         default:
     266            0 :                                                 break;
     267              :                                 }
     268            0 :                         }
     269            0 :                         if (*end == '.')
     270              :                         {
     271              :                                 /* We have var[n].field */
     272            0 :                                 p = find_struct(name, next, end);
     273            0 :                         }
     274              :                         else
     275              :                         {
     276              :                                 /*
     277              :                                  * Note: this part assumes we must just have var[n] without
     278              :                                  * any further decoration, which fails to handle cases such as
     279              :                                  * var[n]->field.  For now, that's okay because
     280              :                                  * pointer-to-pointer variables are rejected elsewhere.
     281              :                                  */
     282            0 :                                 char       *prefix = loc_nstrdup(name, next - name);
     283              : 
     284            0 :                                 p = find_simple(prefix);
     285            0 :                                 if (p == NULL)
     286            0 :                                         mmfatal(PARSE_ERROR, "variable \"%s\" is not declared", prefix);
     287            0 :                                 if (p->type->type != ECPGt_array)
     288            0 :                                         mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer", prefix);
     289            0 :                                 switch (p->type->u.element->type)
     290              :                                 {
     291              :                                         case ECPGt_array:
     292            0 :                                                 return new_variable(name, ECPGmake_array_type(ECPGmake_simple_type(p->type->u.element->u.element->type, p->type->u.element->u.element->size, p->type->u.element->u.element->counter), p->type->u.element->size), p->brace_level);
     293              :                                         case ECPGt_struct:
     294              :                                         case ECPGt_union:
     295            0 :                                                 return new_variable(name, ECPGmake_struct_type(p->type->u.element->u.members, p->type->u.element->type, p->type->u.element->type_name, p->type->u.element->struct_sizeof), p->brace_level);
     296              :                                         default:
     297            0 :                                                 return new_variable(name, ECPGmake_simple_type(p->type->u.element->type, p->type->u.element->size, p->type->u.element->counter), p->brace_level);
     298              :                                 }
     299            0 :                         }
     300            0 :                 }
     301              :                 else
     302              :                 {
     303              :                         /* Must be var.field or var->field */
     304            0 :                         p = find_struct(name, next, next);
     305              :                 }
     306            0 :         }
     307              :         else
     308            0 :                 p = find_simple(name);
     309              : 
     310            0 :         if (p == NULL)
     311            0 :                 mmfatal(PARSE_ERROR, "variable \"%s\" is not declared", name);
     312              : 
     313            0 :         return p;
     314            0 : }
     315              : 
     316              : void
     317            0 : remove_typedefs(int brace_level)
     318              : {
     319            0 :         struct typedefs *p,
     320              :                            *prev,
     321              :                            *next;
     322              : 
     323            0 :         for (p = types, prev = NULL; p; p = next)
     324              :         {
     325            0 :                 next = p->next;
     326            0 :                 if (p->brace_level >= brace_level)
     327              :                 {
     328              :                         /* remove it */
     329            0 :                         if (prev)
     330            0 :                                 prev->next = next;
     331              :                         else
     332            0 :                                 types = next;
     333              : 
     334            0 :                         if (p->type->type_enum == ECPGt_struct || p->type->type_enum == ECPGt_union)
     335            0 :                                 ECPGfree_struct_member(p->struct_member_list);
     336            0 :                         free(p->type->type_storage);
     337            0 :                         free(p->type->type_str);
     338            0 :                         free(p->type->type_dimension);
     339            0 :                         free(p->type->type_index);
     340            0 :                         free(p->type->type_sizeof);
     341            0 :                         free(p->type);
     342            0 :                         free(p->name);
     343            0 :                         free(p);
     344            0 :                 }
     345              :                 else
     346            0 :                         prev = p;
     347            0 :         }
     348            0 : }
     349              : 
     350              : void
     351            0 : remove_variables(int brace_level)
     352              : {
     353            0 :         struct variable *p,
     354              :                            *prev,
     355              :                            *next;
     356              : 
     357            0 :         for (p = allvariables, prev = NULL; p; p = next)
     358              :         {
     359            0 :                 next = p->next;
     360            0 :                 if (p->brace_level >= brace_level)
     361              :                 {
     362              :                         /* remove it, but first remove any references from cursors */
     363            0 :                         struct cursor *ptr;
     364              : 
     365            0 :                         for (ptr = cur; ptr != NULL; ptr = ptr->next)
     366              :                         {
     367            0 :                                 struct arguments *varptr,
     368              :                                                    *prevvar,
     369              :                                                    *nextvar;
     370              : 
     371            0 :                                 for (varptr = ptr->argsinsert, prevvar = NULL;
     372            0 :                                          varptr != NULL; varptr = nextvar)
     373              :                                 {
     374            0 :                                         nextvar = varptr->next;
     375            0 :                                         if (p == varptr->variable)
     376              :                                         {
     377              :                                                 /* remove from list */
     378            0 :                                                 if (prevvar)
     379            0 :                                                         prevvar->next = nextvar;
     380              :                                                 else
     381            0 :                                                         ptr->argsinsert = nextvar;
     382            0 :                                                 free(varptr);
     383            0 :                                         }
     384              :                                         else
     385            0 :                                                 prevvar = varptr;
     386            0 :                                 }
     387            0 :                                 for (varptr = ptr->argsresult, prevvar = NULL;
     388            0 :                                          varptr != NULL; varptr = nextvar)
     389              :                                 {
     390            0 :                                         nextvar = varptr->next;
     391            0 :                                         if (p == varptr->variable)
     392              :                                         {
     393              :                                                 /* remove from list */
     394            0 :                                                 if (prevvar)
     395            0 :                                                         prevvar->next = nextvar;
     396              :                                                 else
     397            0 :                                                         ptr->argsresult = nextvar;
     398            0 :                                                 free(varptr);
     399            0 :                                         }
     400              :                                         else
     401            0 :                                                 prevvar = varptr;
     402            0 :                                 }
     403            0 :                         }
     404              : 
     405              :                         /* remove it */
     406            0 :                         if (prev)
     407            0 :                                 prev->next = next;
     408              :                         else
     409            0 :                                 allvariables = next;
     410              : 
     411            0 :                         ECPGfree_type(p->type);
     412            0 :                         free(p->name);
     413            0 :                         free(p);
     414            0 :                 }
     415              :                 else
     416            0 :                         prev = p;
     417            0 :         }
     418            0 : }
     419              : 
     420              : 
     421              : /*
     422              :  * Here are the variables that need to be handled on every request.
     423              :  * These are of two kinds: input and output.
     424              :  * I will make two lists for them.
     425              :  */
     426              : 
     427              : struct arguments *argsinsert = NULL;
     428              : struct arguments *argsresult = NULL;
     429              : 
     430              : void
     431            0 : reset_variables(void)
     432              : {
     433            0 :         struct arguments *p,
     434              :                            *next;
     435              : 
     436            0 :         for (p = argsinsert; p; p = next)
     437              :         {
     438            0 :                 next = p->next;
     439            0 :                 free(p);
     440            0 :         }
     441            0 :         argsinsert = NULL;
     442            0 :         for (p = argsresult; p; p = next)
     443              :         {
     444            0 :                 next = p->next;
     445            0 :                 free(p);
     446            0 :         }
     447            0 :         argsresult = NULL;
     448            0 : }
     449              : 
     450              : /* Insert a new variable into our request list.
     451              :  * Note: The list is dumped from the end,
     452              :  * so we have to add new entries at the beginning */
     453              : void
     454            0 : add_variable_to_head(struct arguments **list, struct variable *var, struct variable *ind)
     455              : {
     456            0 :         struct arguments *p = (struct arguments *) mm_alloc(sizeof(struct arguments));
     457              : 
     458            0 :         p->variable = var;
     459            0 :         p->indicator = ind;
     460            0 :         p->next = *list;
     461            0 :         *list = p;
     462            0 : }
     463              : 
     464              : /* Append a new variable to our request list. */
     465              : void
     466            0 : add_variable_to_tail(struct arguments **list, struct variable *var, struct variable *ind)
     467              : {
     468            0 :         struct arguments *p,
     469            0 :                            *new = (struct arguments *) mm_alloc(sizeof(struct arguments));
     470              : 
     471            0 :         for (p = *list; p && p->next; p = p->next);
     472              : 
     473            0 :         new->variable = var;
     474            0 :         new->indicator = ind;
     475            0 :         new->next = NULL;
     476              : 
     477            0 :         if (p)
     478            0 :                 p->next = new;
     479              :         else
     480            0 :                 *list = new;
     481            0 : }
     482              : 
     483              : void
     484            0 : remove_variable_from_list(struct arguments **list, struct variable *var)
     485              : {
     486            0 :         struct arguments *p,
     487            0 :                            *prev = NULL;
     488            0 :         bool            found = false;
     489              : 
     490            0 :         for (p = *list; p; p = p->next)
     491              :         {
     492            0 :                 if (p->variable == var)
     493              :                 {
     494            0 :                         found = true;
     495            0 :                         break;
     496              :                 }
     497            0 :                 prev = p;
     498            0 :         }
     499            0 :         if (found)
     500              :         {
     501            0 :                 if (prev)
     502            0 :                         prev->next = p->next;
     503              :                 else
     504            0 :                         *list = p->next;
     505            0 :                 free(p);
     506            0 :         }
     507            0 : }
     508              : 
     509              : /* Dump out a list of all the variable on this list.
     510              :    This is a recursive function that works from the end of the list and
     511              :    deletes the list as we go on.
     512              :  */
     513              : void
     514            0 : dump_variables(struct arguments *list, int mode)
     515              : {
     516            0 :         char       *str_zero;
     517              : 
     518            0 :         if (list == NULL)
     519            0 :                 return;
     520              : 
     521            0 :         str_zero = mm_strdup("0");
     522              : 
     523              :         /*
     524              :          * The list is build up from the beginning so lets first dump the end of
     525              :          * the list:
     526              :          */
     527              : 
     528            0 :         dump_variables(list->next, mode);
     529              : 
     530              :         /* Then the current element and its indicator */
     531            0 :         ECPGdump_a_type(base_yyout, list->variable->name, list->variable->type, list->variable->brace_level,
     532            0 :                                         list->indicator->name, list->indicator->type, list->indicator->brace_level,
     533            0 :                                         NULL, NULL, str_zero, NULL, NULL);
     534              : 
     535              :         /* Then release the list element. */
     536            0 :         if (mode != 0)
     537            0 :                 free(list);
     538              : 
     539            0 :         free(str_zero);
     540            0 : }
     541              : 
     542              : void
     543            0 : check_indicator(struct ECPGtype *var)
     544              : {
     545              :         /* make sure this is a valid indicator variable */
     546            0 :         switch (var->type)
     547              :         {
     548              :                         struct ECPGstruct_member *p;
     549              : 
     550              :                 case ECPGt_short:
     551              :                 case ECPGt_int:
     552              :                 case ECPGt_long:
     553              :                 case ECPGt_long_long:
     554              :                 case ECPGt_unsigned_short:
     555              :                 case ECPGt_unsigned_int:
     556              :                 case ECPGt_unsigned_long:
     557              :                 case ECPGt_unsigned_long_long:
     558            0 :                         break;
     559              : 
     560              :                 case ECPGt_struct:
     561              :                 case ECPGt_union:
     562            0 :                         for (p = var->u.members; p; p = p->next)
     563            0 :                                 check_indicator(p->type);
     564            0 :                         break;
     565              : 
     566              :                 case ECPGt_array:
     567            0 :                         check_indicator(var->u.element);
     568            0 :                         break;
     569              :                 default:
     570            0 :                         mmerror(PARSE_ERROR, ET_ERROR, "indicator variable must have an integer type");
     571            0 :                         break;
     572              :         }
     573            0 : }
     574              : 
     575              : struct typedefs *
     576            0 : get_typedef(const char *name, bool noerror)
     577              : {
     578            0 :         struct typedefs *this;
     579              : 
     580            0 :         for (this = types; this != NULL; this = this->next)
     581              :         {
     582            0 :                 if (strcmp(this->name, name) == 0)
     583            0 :                         return this;
     584            0 :         }
     585              : 
     586            0 :         if (!noerror)
     587            0 :                 mmfatal(PARSE_ERROR, "unrecognized data type name \"%s\"", name);
     588              : 
     589            0 :         return NULL;
     590            0 : }
     591              : 
     592              : void
     593            0 : adjust_array(enum ECPGttype type_enum,
     594              :                          const char **dimension, const char **length,
     595              :                          const char *type_dimension, const char *type_index,
     596              :                          int pointer_len, bool type_definition)
     597              : {
     598            0 :         if (atoi(type_index) >= 0)
     599              :         {
     600            0 :                 if (atoi(*length) >= 0)
     601            0 :                         mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
     602              : 
     603            0 :                 *length = type_index;
     604            0 :         }
     605              : 
     606            0 :         if (atoi(type_dimension) >= 0)
     607              :         {
     608            0 :                 if (atoi(*dimension) >= 0 && atoi(*length) >= 0)
     609            0 :                         mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
     610              : 
     611            0 :                 if (atoi(*dimension) >= 0)
     612            0 :                         *length = *dimension;
     613              : 
     614            0 :                 *dimension = type_dimension;
     615            0 :         }
     616              : 
     617            0 :         if (pointer_len > 2)
     618            0 :                 mmfatal(PARSE_ERROR, ngettext("multilevel pointers (more than 2 levels) are not supported; found %d level",
     619            0 :                                                                           "multilevel pointers (more than 2 levels) are not supported; found %d levels", pointer_len),
     620            0 :                                 pointer_len);
     621              : 
     622            0 :         if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char && type_enum != ECPGt_string)
     623            0 :                 mmfatal(PARSE_ERROR, "pointer to pointer is not supported for this data type");
     624              : 
     625            0 :         if (pointer_len > 1 && (atoi(*length) >= 0 || atoi(*dimension) >= 0))
     626            0 :                 mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
     627              : 
     628            0 :         if (atoi(*length) >= 0 && atoi(*dimension) >= 0 && pointer_len)
     629            0 :                 mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
     630              : 
     631            0 :         switch (type_enum)
     632              :         {
     633              :                 case ECPGt_struct:
     634              :                 case ECPGt_union:
     635              :                         /* pointer has to get dimension 0 */
     636            0 :                         if (pointer_len)
     637              :                         {
     638            0 :                                 *length = *dimension;
     639            0 :                                 *dimension = "0";
     640            0 :                         }
     641              : 
     642            0 :                         if (atoi(*length) >= 0)
     643            0 :                                 mmfatal(PARSE_ERROR, "multidimensional arrays for structures are not supported");
     644              : 
     645            0 :                         break;
     646              :                 case ECPGt_varchar:
     647              :                 case ECPGt_bytea:
     648              :                         /* pointer has to get dimension 0 */
     649            0 :                         if (pointer_len)
     650            0 :                                 *dimension = "0";
     651              : 
     652              :                         /* one index is the string length */
     653            0 :                         if (atoi(*length) < 0)
     654              :                         {
     655            0 :                                 *length = *dimension;
     656            0 :                                 *dimension = "-1";
     657            0 :                         }
     658              : 
     659            0 :                         break;
     660              :                 case ECPGt_char:
     661              :                 case ECPGt_unsigned_char:
     662              :                 case ECPGt_string:
     663              :                         /* char ** */
     664            0 :                         if (pointer_len == 2)
     665              :                         {
     666            0 :                                 *length = *dimension = "0";
     667            0 :                                 break;
     668              :                         }
     669              : 
     670              :                         /* pointer has to get length 0 */
     671            0 :                         if (pointer_len == 1)
     672            0 :                                 *length = "0";
     673              : 
     674              :                         /* one index is the string length */
     675            0 :                         if (atoi(*length) < 0)
     676              :                         {
     677              :                                 /*
     678              :                                  * make sure we return length = -1 for arrays without given
     679              :                                  * bounds
     680              :                                  */
     681            0 :                                 if (atoi(*dimension) < 0 && !type_definition)
     682              : 
     683              :                                         /*
     684              :                                          * do not change this for typedefs since it will be
     685              :                                          * changed later on when the variable is defined
     686              :                                          */
     687            0 :                                         *length = "1";
     688            0 :                                 else if (strcmp(*dimension, "0") == 0)
     689            0 :                                         *length = "-1";
     690              :                                 else
     691            0 :                                         *length = *dimension;
     692              : 
     693            0 :                                 *dimension = "-1";
     694            0 :                         }
     695            0 :                         break;
     696              :                 default:
     697              :                         /* a pointer has dimension = 0 */
     698            0 :                         if (pointer_len)
     699              :                         {
     700            0 :                                 *length = *dimension;
     701            0 :                                 *dimension = "0";
     702            0 :                         }
     703              : 
     704            0 :                         if (atoi(*length) >= 0)
     705            0 :                                 mmfatal(PARSE_ERROR, "multidimensional arrays for simple data types are not supported");
     706              : 
     707            0 :                         break;
     708              :         }
     709            0 : }
        

Generated by: LCOV version 2.3.2-1