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

Generated by: LCOV version 1.16