LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/preproc - variable.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 79.3 % 300 238
Test Date: 2026-03-03 13:15:30 Functions: 100.0 % 16 16
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          165 : loc_nstrdup(const char *in, size_t len)
      12              : {
      13              :     char       *out;
      14              : 
      15          165 :     out = loc_alloc(len + 1);
      16          165 :     memcpy(out, in, len);
      17          165 :     out[len] = '\0';
      18              : 
      19          165 :     return out;
      20              : }
      21              : 
      22              : struct variable *
      23          520 : new_variable(const char *name, struct ECPGtype *type, int brace_level)
      24              : {
      25          520 :     struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable));
      26              : 
      27          520 :     p->name = mm_strdup(name);
      28          520 :     p->type = type;
      29          520 :     p->brace_level = brace_level;
      30              : 
      31          520 :     p->next = allvariables;
      32          520 :     allvariables = p;
      33              : 
      34          520 :     return p;
      35              : }
      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           65 : 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           65 :     const char *next = strpbrk(++str, ".-["),
      54              :                *end,
      55              :                *field;
      56              : 
      57           65 :     if (next != NULL)
      58           12 :         field = loc_nstrdup(str, next - str);
      59              :     else
      60           53 :         field = str;
      61              : 
      62          104 :     for (; members; members = members->next)
      63              :     {
      64          104 :         if (strcmp(members->name, field) == 0)
      65              :         {
      66           65 :             if (next == NULL)
      67              :             {
      68              :                 /* found the end */
      69           53 :                 switch (members->type->type)
      70              :                 {
      71            0 :                     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            0 :                     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           53 :                     default:
      77           53 :                         return new_variable(name, ECPGmake_simple_type(members->type->type, members->type->size, members->type->counter), brace_level);
      78              :                 }
      79              :             }
      80              :             else
      81              :             {
      82           12 :                 if (*next == '[')
      83              :                 {
      84              :                     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           36 :                     for (count = 1, end = next + 1; count; end++)
      91              :                     {
      92           24 :                         switch (*end)
      93              :                         {
      94            0 :                             case '[':
      95            0 :                                 count++;
      96            0 :                                 break;
      97           12 :                             case ']':
      98           12 :                                 count--;
      99           12 :                                 break;
     100           12 :                             default:
     101           12 :                                 break;
     102              :                         }
     103              :                     }
     104              :                 }
     105              :                 else
     106            0 :                     end = next;
     107              : 
     108           12 :                 switch (*end)
     109              :                 {
     110            0 :                     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            0 :                             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            0 :                             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            0 :                             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            0 :                     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           12 :                     case '.':
     133           12 :                         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           12 :                             return find_struct_member(name, end, members->type->u.members, brace_level);
     137              :                         break;
     138            0 :                     default:
     139            0 :                         mmfatal(PARSE_ERROR, "incorrectly formed variable \"%s\"", name);
     140              :                         break;
     141              :                 }
     142              :             }
     143              :         }
     144              :     }
     145              : 
     146            0 :     return NULL;
     147              : }
     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           53 : find_struct(const char *name, const char *next, const char *end)
     162              : {
     163              :     char       *prefix;
     164              :     struct variable *p;
     165              : 
     166              :     /* first get the mother structure entry */
     167           53 :     prefix = loc_nstrdup(name, next - name);
     168           53 :     p = find_variable(prefix);
     169              : 
     170           53 :     if (*next == '-')
     171              :     {
     172              :         /* We have var->field */
     173            6 :         if (p->type->type != ECPGt_array)
     174            0 :             mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer", prefix);
     175              : 
     176            6 :         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            6 :         return find_struct_member(name, ++end, p->type->u.element->u.members, p->brace_level);
     180              :     }
     181              :     else
     182              :     {
     183           47 :         if (next == end)
     184              :         {
     185              :             /* We have var.field */
     186           41 :             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           41 :             return find_struct_member(name, end, p->type->u.members, p->brace_level);
     190              :         }
     191              :         else
     192              :         {
     193              :             /* We have var[n].field */
     194            6 :             if (p->type->type != ECPGt_array)
     195            0 :                 mmfatal(PARSE_ERROR, "variable \"%s\" is not an array", prefix);
     196              : 
     197            6 :             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            6 :             return find_struct_member(name, end, p->type->u.element->u.members, p->brace_level);
     201              :         }
     202              :     }
     203              : }
     204              : 
     205              : /* Look up a variable given its base name */
     206              : static struct variable *
     207         1389 : find_simple(const char *name)
     208              : {
     209              :     struct variable *p;
     210              : 
     211        11497 :     for (p = allvariables; p; p = p->next)
     212              :     {
     213        11497 :         if (strcmp(p->name, name) == 0)
     214         1389 :             return p;
     215              :     }
     216              : 
     217            0 :     return NULL;
     218              : }
     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         1442 : find_variable(const char *name)
     236              : {
     237              :     const char *next,
     238              :                *end;
     239              :     struct variable *p;
     240              :     int         count;
     241              : 
     242         1442 :     next = strpbrk(name, ".[-");
     243         1442 :     if (next)
     244              :     {
     245              :         /* Deal with field/subscript decoration */
     246          153 :         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          318 :             for (count = 1, end = next + 1; count; end++)
     253              :             {
     254          212 :                 switch (*end)
     255              :                 {
     256            0 :                     case '[':
     257            0 :                         count++;
     258            0 :                         break;
     259          106 :                     case ']':
     260          106 :                         count--;
     261          106 :                         break;
     262            0 :                     case '\0':
     263            0 :                         mmfatal(PARSE_ERROR, "unmatched bracket in variable \"%s\"", name);
     264              :                         break;
     265          106 :                     default:
     266          106 :                         break;
     267              :                 }
     268              :             }
     269          106 :             if (*end == '.')
     270              :             {
     271              :                 /* We have var[n].field */
     272            6 :                 p = find_struct(name, next, end);
     273              :             }
     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          100 :                 char       *prefix = loc_nstrdup(name, next - name);
     283              : 
     284          100 :                 p = find_simple(prefix);
     285          100 :                 if (p == NULL)
     286            0 :                     mmfatal(PARSE_ERROR, "variable \"%s\" is not declared", prefix);
     287          100 :                 if (p->type->type != ECPGt_array)
     288            0 :                     mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer", prefix);
     289          100 :                 switch (p->type->u.element->type)
     290              :                 {
     291            0 :                     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            3 :                     case ECPGt_struct:
     294              :                     case ECPGt_union:
     295            3 :                         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           97 :                     default:
     297           97 :                         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              :             }
     300              :         }
     301              :         else
     302              :         {
     303              :             /* Must be var.field or var->field */
     304           47 :             p = find_struct(name, next, next);
     305              :         }
     306              :     }
     307              :     else
     308         1289 :         p = find_simple(name);
     309              : 
     310         1342 :     if (p == NULL)
     311            0 :         mmfatal(PARSE_ERROR, "variable \"%s\" is not declared", name);
     312              : 
     313         1342 :     return p;
     314              : }
     315              : 
     316              : void
     317          331 : remove_typedefs(int brace_level)
     318              : {
     319              :     struct typedefs *p,
     320              :                *prev,
     321              :                *next;
     322              : 
     323          495 :     for (p = types, prev = NULL; p; p = next)
     324              :     {
     325          164 :         next = p->next;
     326          164 :         if (p->brace_level >= brace_level)
     327              :         {
     328              :             /* remove it */
     329           14 :             if (prev)
     330            0 :                 prev->next = next;
     331              :             else
     332           14 :                 types = next;
     333              : 
     334           14 :             if (p->type->type_enum == ECPGt_struct || p->type->type_enum == ECPGt_union)
     335           12 :                 ECPGfree_struct_member(p->struct_member_list);
     336           14 :             free(p->type->type_storage);
     337           14 :             free(p->type->type_str);
     338           14 :             free(p->type->type_dimension);
     339           14 :             free(p->type->type_index);
     340           14 :             free(p->type->type_sizeof);
     341           14 :             free(p->type);
     342           14 :             free(p->name);
     343           14 :             free(p);
     344              :         }
     345              :         else
     346          150 :             prev = p;
     347              :     }
     348          331 : }
     349              : 
     350              : void
     351          331 : remove_variables(int brace_level)
     352              : {
     353              :     struct variable *p,
     354              :                *prev,
     355              :                *next;
     356              : 
     357         1673 :     for (p = allvariables, prev = NULL; p; p = next)
     358              :     {
     359         1342 :         next = p->next;
     360         1342 :         if (p->brace_level >= brace_level)
     361              :         {
     362              :             /* remove it, but first remove any references from cursors */
     363              :             struct cursor *ptr;
     364              : 
     365          789 :             for (ptr = cur; ptr != NULL; ptr = ptr->next)
     366              :             {
     367              :                 struct arguments *varptr,
     368              :                            *prevvar,
     369              :                            *nextvar;
     370              : 
     371          369 :                 for (varptr = ptr->argsinsert, prevvar = NULL;
     372          630 :                      varptr != NULL; varptr = nextvar)
     373              :                 {
     374          261 :                     nextvar = varptr->next;
     375          261 :                     if (p == varptr->variable)
     376              :                     {
     377              :                         /* remove from list */
     378           12 :                         if (prevvar)
     379            3 :                             prevvar->next = nextvar;
     380              :                         else
     381            9 :                             ptr->argsinsert = nextvar;
     382           12 :                         free(varptr);
     383              :                     }
     384              :                     else
     385          249 :                         prevvar = varptr;
     386              :                 }
     387          369 :                 for (varptr = ptr->argsresult, prevvar = NULL;
     388          374 :                      varptr != NULL; varptr = nextvar)
     389              :                 {
     390            5 :                     nextvar = varptr->next;
     391            5 :                     if (p == varptr->variable)
     392              :                     {
     393              :                         /* remove from list */
     394            3 :                         if (prevvar)
     395            0 :                             prevvar->next = nextvar;
     396              :                         else
     397            3 :                             ptr->argsresult = nextvar;
     398            3 :                         free(varptr);
     399              :                     }
     400              :                     else
     401            2 :                         prevvar = varptr;
     402              :                 }
     403              :             }
     404              : 
     405              :             /* remove it */
     406          420 :             if (prev)
     407          163 :                 prev->next = next;
     408              :             else
     409          257 :                 allvariables = next;
     410              : 
     411          420 :             ECPGfree_type(p->type);
     412          420 :             free(p->name);
     413          420 :             free(p);
     414              :         }
     415              :         else
     416          922 :             prev = p;
     417              :     }
     418          331 : }
     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         1454 : reset_variables(void)
     432              : {
     433              :     struct arguments *p,
     434              :                *next;
     435              : 
     436         1456 :     for (p = argsinsert; p; p = next)
     437              :     {
     438            2 :         next = p->next;
     439            2 :         free(p);
     440              :     }
     441         1454 :     argsinsert = NULL;
     442         1454 :     for (p = argsresult; p; p = next)
     443              :     {
     444            0 :         next = p->next;
     445            0 :         free(p);
     446              :     }
     447         1454 :     argsresult = NULL;
     448         1454 : }
     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          514 : add_variable_to_head(struct arguments **list, struct variable *var, struct variable *ind)
     455              : {
     456          514 :     struct arguments *p = (struct arguments *) mm_alloc(sizeof(struct arguments));
     457              : 
     458          514 :     p->variable = var;
     459          514 :     p->indicator = ind;
     460          514 :     p->next = *list;
     461          514 :     *list = p;
     462          514 : }
     463              : 
     464              : /* Append a new variable to our request list. */
     465              : void
     466           97 : add_variable_to_tail(struct arguments **list, struct variable *var, struct variable *ind)
     467              : {
     468              :     struct arguments *p,
     469           97 :                *new = (struct arguments *) mm_alloc(sizeof(struct arguments));
     470              : 
     471          104 :     for (p = *list; p && p->next; p = p->next);
     472              : 
     473           97 :     new->variable = var;
     474           97 :     new->indicator = ind;
     475           97 :     new->next = NULL;
     476              : 
     477           97 :     if (p)
     478           26 :         p->next = new;
     479              :     else
     480           71 :         *list = new;
     481           97 : }
     482              : 
     483              : void
     484           17 : remove_variable_from_list(struct arguments **list, struct variable *var)
     485              : {
     486              :     struct arguments *p,
     487           17 :                *prev = NULL;
     488           17 :     bool        found = false;
     489              : 
     490           17 :     for (p = *list; p; p = p->next)
     491              :     {
     492           17 :         if (p->variable == var)
     493              :         {
     494           17 :             found = true;
     495           17 :             break;
     496              :         }
     497            0 :         prev = p;
     498              :     }
     499           17 :     if (found)
     500              :     {
     501           17 :         if (prev)
     502            0 :             prev->next = p->next;
     503              :         else
     504           17 :             *list = p->next;
     505           17 :         free(p);
     506              :     }
     507           17 : }
     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         1647 : dump_variables(struct arguments *list, int mode)
     515              : {
     516              :     char       *str_zero;
     517              : 
     518         1647 :     if (list == NULL)
     519         1125 :         return;
     520              : 
     521          522 :     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          522 :     dump_variables(list->next, mode);
     529              : 
     530              :     /* Then the current element and its indicator */
     531          522 :     ECPGdump_a_type(base_yyout, list->variable->name, list->variable->type, list->variable->brace_level,
     532          522 :                     list->indicator->name, list->indicator->type, list->indicator->brace_level,
     533              :                     NULL, NULL, str_zero, NULL, NULL);
     534              : 
     535              :     /* Then release the list element. */
     536          522 :     if (mode != 0)
     537          522 :         free(list);
     538              : 
     539          522 :     free(str_zero);
     540              : }
     541              : 
     542              : void
     543           67 : check_indicator(struct ECPGtype *var)
     544              : {
     545              :     /* make sure this is a valid indicator variable */
     546           67 :     switch (var->type)
     547              :     {
     548              :             struct ECPGstruct_member *p;
     549              : 
     550           45 :         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           45 :             break;
     559              : 
     560           11 :         case ECPGt_struct:
     561              :         case ECPGt_union:
     562           36 :             for (p = var->u.members; p; p = p->next)
     563           25 :                 check_indicator(p->type);
     564           11 :             break;
     565              : 
     566           11 :         case ECPGt_array:
     567           11 :             check_indicator(var->u.element);
     568           11 :             break;
     569            0 :         default:
     570            0 :             mmerror(PARSE_ERROR, ET_ERROR, "indicator variable must have an integer type");
     571            0 :             break;
     572              :     }
     573           67 : }
     574              : 
     575              : struct typedefs *
     576         5670 : get_typedef(const char *name, bool noerror)
     577              : {
     578              :     struct typedefs *this;
     579              : 
     580         9267 :     for (this = types; this != NULL; this = this->next)
     581              :     {
     582         3633 :         if (strcmp(this->name, name) == 0)
     583           36 :             return this;
     584              :     }
     585              : 
     586         5634 :     if (!noerror)
     587            0 :         mmfatal(PARSE_ERROR, "unrecognized data type name \"%s\"", name);
     588              : 
     589         5634 :     return NULL;
     590              : }
     591              : 
     592              : void
     593          392 : 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          392 :     if (atoi(type_index) >= 0)
     599              :     {
     600            6 :         if (atoi(*length) >= 0)
     601            0 :             mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
     602              : 
     603            6 :         *length = type_index;
     604              :     }
     605              : 
     606          392 :     if (atoi(type_dimension) >= 0)
     607              :     {
     608            1 :         if (atoi(*dimension) >= 0 && atoi(*length) >= 0)
     609            0 :             mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
     610              : 
     611            1 :         if (atoi(*dimension) >= 0)
     612            0 :             *length = *dimension;
     613              : 
     614            1 :         *dimension = type_dimension;
     615              :     }
     616              : 
     617          392 :     if (pointer_len > 2)
     618            0 :         mmfatal(PARSE_ERROR, ngettext("multilevel pointers (more than 2 levels) are not supported; found %d level",
     619              :                                       "multilevel pointers (more than 2 levels) are not supported; found %d levels", pointer_len),
     620              :                 pointer_len);
     621              : 
     622          392 :     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          392 :     if (pointer_len > 1 && (atoi(*length) >= 0 || atoi(*dimension) >= 0))
     626            0 :         mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
     627              : 
     628          392 :     if (atoi(*length) >= 0 && atoi(*dimension) >= 0 && pointer_len)
     629            0 :         mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
     630              : 
     631          392 :     switch (type_enum)
     632              :     {
     633           40 :         case ECPGt_struct:
     634              :         case ECPGt_union:
     635              :             /* pointer has to get dimension 0 */
     636           40 :             if (pointer_len)
     637              :             {
     638           10 :                 *length = *dimension;
     639           10 :                 *dimension = "0";
     640              :             }
     641              : 
     642           40 :             if (atoi(*length) >= 0)
     643            0 :                 mmfatal(PARSE_ERROR, "multidimensional arrays for structures are not supported");
     644              : 
     645           40 :             break;
     646           23 :         case ECPGt_varchar:
     647              :         case ECPGt_bytea:
     648              :             /* pointer has to get dimension 0 */
     649           23 :             if (pointer_len)
     650            0 :                 *dimension = "0";
     651              : 
     652              :             /* one index is the string length */
     653           23 :             if (atoi(*length) < 0)
     654              :             {
     655           15 :                 *length = *dimension;
     656           15 :                 *dimension = "-1";
     657              :             }
     658              : 
     659           23 :             break;
     660          129 :         case ECPGt_char:
     661              :         case ECPGt_unsigned_char:
     662              :         case ECPGt_string:
     663              :             /* char ** */
     664          129 :             if (pointer_len == 2)
     665              :             {
     666            8 :                 *length = *dimension = "0";
     667            8 :                 break;
     668              :             }
     669              : 
     670              :             /* pointer has to get length 0 */
     671          121 :             if (pointer_len == 1)
     672           45 :                 *length = "0";
     673              : 
     674              :             /* one index is the string length */
     675          121 :             if (atoi(*length) < 0)
     676              :             {
     677              :                 /*
     678              :                  * make sure we return length = -1 for arrays without given
     679              :                  * bounds
     680              :                  */
     681           66 :                 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            5 :                     *length = "1";
     688           61 :                 else if (strcmp(*dimension, "0") == 0)
     689            2 :                     *length = "-1";
     690              :                 else
     691           59 :                     *length = *dimension;
     692              : 
     693           66 :                 *dimension = "-1";
     694              :             }
     695          121 :             break;
     696          200 :         default:
     697              :             /* a pointer has dimension = 0 */
     698          200 :             if (pointer_len)
     699              :             {
     700           20 :                 *length = *dimension;
     701           20 :                 *dimension = "0";
     702              :             }
     703              : 
     704          200 :             if (atoi(*length) >= 0)
     705            0 :                 mmfatal(PARSE_ERROR, "multidimensional arrays for simple data types are not supported");
     706              : 
     707          200 :             break;
     708              :     }
     709          392 : }
        

Generated by: LCOV version 2.0-1