LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/preproc - variable.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 79.3 % 300 238
Test Date: 2026-07-12 22:15:32 Functions: 100.0 % 16 16
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 70.3 % 202 142

             Branch data     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                 :         531 : new_variable(const char *name, struct ECPGtype *type, int brace_level)
      24                 :             : {
      25                 :         531 :     struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable));
      26                 :             : 
      27                 :         531 :     p->name = mm_strdup(name);
      28                 :         531 :     p->type = type;
      29                 :         531 :     p->brace_level = brace_level;
      30                 :             : 
      31                 :         531 :     p->next = allvariables;
      32                 :         531 :     allvariables = p;
      33                 :             : 
      34                 :         531 :     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                 :        1421 : find_simple(const char *name)
     208                 :             : {
     209                 :             :     struct variable *p;
     210                 :             : 
     211         [ +  - ]:       11578 :     for (p = allvariables; p; p = p->next)
     212                 :             :     {
     213         [ +  + ]:       11578 :         if (strcmp(p->name, name) == 0)
     214                 :        1421 :             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                 :        1474 : find_variable(const char *name)
     236                 :             : {
     237                 :             :     const char *next,
     238                 :             :                *end;
     239                 :             :     struct variable *p;
     240                 :             :     int         count;
     241                 :             : 
     242                 :        1474 :     next = strpbrk(name, ".[-");
     243         [ +  + ]:        1474 :     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                 :        1321 :         p = find_simple(name);
     309                 :             : 
     310         [ -  + ]:        1374 :     if (p == NULL)
     311                 :           0 :         mmfatal(PARSE_ERROR, "variable \"%s\" is not declared", name);
     312                 :             : 
     313                 :        1374 :     return p;
     314                 :             : }
     315                 :             : 
     316                 :             : void
     317                 :         334 : remove_typedefs(int brace_level)
     318                 :             : {
     319                 :             :     struct typedefs *p,
     320                 :             :                *prev,
     321                 :             :                *next;
     322                 :             : 
     323         [ +  + ]:         498 :     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                 :         334 : }
     349                 :             : 
     350                 :             : void
     351                 :         334 : remove_variables(int brace_level)
     352                 :             : {
     353                 :             :     struct variable *p,
     354                 :             :                *prev,
     355                 :             :                *next;
     356                 :             : 
     357         [ +  + ]:        1691 :     for (p = allvariables, prev = NULL; p; p = next)
     358                 :             :     {
     359                 :        1357 :         next = p->next;
     360         [ +  + ]:        1357 :         if (p->brace_level >= brace_level)
     361                 :             :         {
     362                 :             :             /* remove it, but first remove any references from cursors */
     363                 :             :             struct cursor *ptr;
     364                 :             : 
     365         [ +  + ]:         805 :             for (ptr = cur; ptr != NULL; ptr = ptr->next)
     366                 :             :             {
     367                 :             :                 struct arguments *varptr,
     368                 :             :                            *prevvar,
     369                 :             :                            *nextvar;
     370                 :             : 
     371                 :         377 :                 for (varptr = ptr->argsinsert, prevvar = NULL;
     372         [ +  + ]:         642 :                      varptr != NULL; varptr = nextvar)
     373                 :             :                 {
     374                 :         265 :                     nextvar = varptr->next;
     375         [ +  + ]:         265 :                     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                 :         253 :                         prevvar = varptr;
     386                 :             :                 }
     387                 :         377 :                 for (varptr = ptr->argsresult, prevvar = NULL;
     388         [ +  + ]:         382 :                      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         [ +  + ]:         428 :             if (prev)
     407                 :         167 :                 prev->next = next;
     408                 :             :             else
     409                 :         261 :                 allvariables = next;
     410                 :             : 
     411                 :         428 :             ECPGfree_type(p->type);
     412                 :         428 :             free(p->name);
     413                 :         428 :             free(p);
     414                 :             :         }
     415                 :             :         else
     416                 :         929 :             prev = p;
     417                 :             :     }
     418                 :         334 : }
     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                 :        1508 : reset_variables(void)
     432                 :             : {
     433                 :             :     struct arguments *p,
     434                 :             :                *next;
     435                 :             : 
     436         [ +  + ]:        1510 :     for (p = argsinsert; p; p = next)
     437                 :             :     {
     438                 :           2 :         next = p->next;
     439                 :           2 :         free(p);
     440                 :             :     }
     441                 :        1508 :     argsinsert = NULL;
     442         [ -  + ]:        1508 :     for (p = argsresult; p; p = next)
     443                 :             :     {
     444                 :           0 :         next = p->next;
     445                 :           0 :         free(p);
     446                 :             :     }
     447                 :        1508 :     argsresult = NULL;
     448                 :        1508 : }
     449                 :             : 
     450                 :             : /*
     451                 :             :  * Insert a new variable into our request list.
     452                 :             :  * Note: The list is dumped from the end,
     453                 :             :  * so we have to add new entries at the beginning
     454                 :             :  */
     455                 :             : void
     456                 :         528 : add_variable_to_head(struct arguments **list, struct variable *var, struct variable *ind)
     457                 :             : {
     458                 :         528 :     struct arguments *p = (struct arguments *) mm_alloc(sizeof(struct arguments));
     459                 :             : 
     460                 :         528 :     p->variable = var;
     461                 :         528 :     p->indicator = ind;
     462                 :         528 :     p->next = *list;
     463                 :         528 :     *list = p;
     464                 :         528 : }
     465                 :             : 
     466                 :             : /* Append a new variable to our request list. */
     467                 :             : void
     468                 :          99 : add_variable_to_tail(struct arguments **list, struct variable *var, struct variable *ind)
     469                 :             : {
     470                 :             :     struct arguments *p,
     471                 :          99 :                *new = (struct arguments *) mm_alloc(sizeof(struct arguments));
     472                 :             : 
     473   [ +  +  +  + ]:         106 :     for (p = *list; p && p->next; p = p->next);
     474                 :             : 
     475                 :          99 :     new->variable = var;
     476                 :          99 :     new->indicator = ind;
     477                 :          99 :     new->next = NULL;
     478                 :             : 
     479         [ +  + ]:          99 :     if (p)
     480                 :          26 :         p->next = new;
     481                 :             :     else
     482                 :          73 :         *list = new;
     483                 :          99 : }
     484                 :             : 
     485                 :             : void
     486                 :          17 : remove_variable_from_list(struct arguments **list, struct variable *var)
     487                 :             : {
     488                 :             :     struct arguments *p,
     489                 :          17 :                *prev = NULL;
     490                 :          17 :     bool        found = false;
     491                 :             : 
     492         [ +  - ]:          17 :     for (p = *list; p; p = p->next)
     493                 :             :     {
     494         [ +  - ]:          17 :         if (p->variable == var)
     495                 :             :         {
     496                 :          17 :             found = true;
     497                 :          17 :             break;
     498                 :             :         }
     499                 :           0 :         prev = p;
     500                 :             :     }
     501         [ +  - ]:          17 :     if (found)
     502                 :             :     {
     503         [ -  + ]:          17 :         if (prev)
     504                 :           0 :             prev->next = p->next;
     505                 :             :         else
     506                 :          17 :             *list = p->next;
     507                 :          17 :         free(p);
     508                 :             :     }
     509                 :          17 : }
     510                 :             : 
     511                 :             : /*
     512                 :             :  * Dump out a list of all the variable on this list.
     513                 :             :  * This is a recursive function that works from the end of the list and
     514                 :             :  * deletes the list as we go on.
     515                 :             :  */
     516                 :             : void
     517                 :        1711 : dump_variables(struct arguments *list, int mode)
     518                 :             : {
     519                 :             :     char       *str_zero;
     520                 :             : 
     521         [ +  + ]:        1711 :     if (list == NULL)
     522                 :        1175 :         return;
     523                 :             : 
     524                 :         536 :     str_zero = mm_strdup("0");
     525                 :             : 
     526                 :             :     /*
     527                 :             :      * The list is build up from the beginning so lets first dump the end of
     528                 :             :      * the list:
     529                 :             :      */
     530                 :             : 
     531                 :         536 :     dump_variables(list->next, mode);
     532                 :             : 
     533                 :             :     /* Then the current element and its indicator */
     534                 :         536 :     ECPGdump_a_type(base_yyout, list->variable->name, list->variable->type, list->variable->brace_level,
     535                 :         536 :                     list->indicator->name, list->indicator->type, list->indicator->brace_level,
     536                 :             :                     NULL, NULL, str_zero, NULL, NULL);
     537                 :             : 
     538                 :             :     /* Then release the list element. */
     539         [ +  - ]:         536 :     if (mode != 0)
     540                 :         536 :         free(list);
     541                 :             : 
     542                 :         536 :     free(str_zero);
     543                 :             : }
     544                 :             : 
     545                 :             : void
     546                 :          67 : check_indicator(struct ECPGtype *var)
     547                 :             : {
     548                 :             :     /* make sure this is a valid indicator variable */
     549   [ +  +  +  - ]:          67 :     switch (var->type)
     550                 :             :     {
     551                 :             :             struct ECPGstruct_member *p;
     552                 :             : 
     553                 :          45 :         case ECPGt_short:
     554                 :             :         case ECPGt_int:
     555                 :             :         case ECPGt_long:
     556                 :             :         case ECPGt_long_long:
     557                 :             :         case ECPGt_unsigned_short:
     558                 :             :         case ECPGt_unsigned_int:
     559                 :             :         case ECPGt_unsigned_long:
     560                 :             :         case ECPGt_unsigned_long_long:
     561                 :          45 :             break;
     562                 :             : 
     563                 :          11 :         case ECPGt_struct:
     564                 :             :         case ECPGt_union:
     565         [ +  + ]:          36 :             for (p = var->u.members; p; p = p->next)
     566                 :          25 :                 check_indicator(p->type);
     567                 :          11 :             break;
     568                 :             : 
     569                 :          11 :         case ECPGt_array:
     570                 :          11 :             check_indicator(var->u.element);
     571                 :          11 :             break;
     572                 :           0 :         default:
     573                 :           0 :             mmerror(PARSE_ERROR, ET_ERROR, "indicator variable must have an integer type");
     574                 :           0 :             break;
     575                 :             :     }
     576                 :          67 : }
     577                 :             : 
     578                 :             : struct typedefs *
     579                 :        5978 : get_typedef(const char *name, bool noerror)
     580                 :             : {
     581                 :             :     struct typedefs *this;
     582                 :             : 
     583         [ +  + ]:        9575 :     for (this = types; this != NULL; this = this->next)
     584                 :             :     {
     585         [ +  + ]:        3633 :         if (strcmp(this->name, name) == 0)
     586                 :          36 :             return this;
     587                 :             :     }
     588                 :             : 
     589         [ -  + ]:        5942 :     if (!noerror)
     590                 :           0 :         mmfatal(PARSE_ERROR, "unrecognized data type name \"%s\"", name);
     591                 :             : 
     592                 :        5942 :     return NULL;
     593                 :             : }
     594                 :             : 
     595                 :             : void
     596                 :         400 : adjust_array(enum ECPGttype type_enum,
     597                 :             :              const char **dimension, const char **length,
     598                 :             :              const char *type_dimension, const char *type_index,
     599                 :             :              int pointer_len, bool type_definition)
     600                 :             : {
     601         [ +  + ]:         400 :     if (atoi(type_index) >= 0)
     602                 :             :     {
     603         [ -  + ]:           6 :         if (atoi(*length) >= 0)
     604                 :           0 :             mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
     605                 :             : 
     606                 :           6 :         *length = type_index;
     607                 :             :     }
     608                 :             : 
     609         [ +  + ]:         400 :     if (atoi(type_dimension) >= 0)
     610                 :             :     {
     611   [ -  +  -  - ]:           1 :         if (atoi(*dimension) >= 0 && atoi(*length) >= 0)
     612                 :           0 :             mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
     613                 :             : 
     614         [ -  + ]:           1 :         if (atoi(*dimension) >= 0)
     615                 :           0 :             *length = *dimension;
     616                 :             : 
     617                 :           1 :         *dimension = type_dimension;
     618                 :             :     }
     619                 :             : 
     620         [ -  + ]:         400 :     if (pointer_len > 2)
     621                 :           0 :         mmfatal(PARSE_ERROR, ngettext("multilevel pointers (more than 2 levels) are not supported; found %d level",
     622                 :             :                                       "multilevel pointers (more than 2 levels) are not supported; found %d levels", pointer_len),
     623                 :             :                 pointer_len);
     624                 :             : 
     625   [ +  +  -  +  :         400 :     if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char && type_enum != ECPGt_string)
             -  -  -  - ]
     626                 :           0 :         mmfatal(PARSE_ERROR, "pointer to pointer is not supported for this data type");
     627                 :             : 
     628   [ +  +  +  -  :         400 :     if (pointer_len > 1 && (atoi(*length) >= 0 || atoi(*dimension) >= 0))
                   -  + ]
     629                 :           0 :         mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
     630                 :             : 
     631   [ +  +  +  +  :         400 :     if (atoi(*length) >= 0 && atoi(*dimension) >= 0 && pointer_len)
                   -  + ]
     632                 :           0 :         mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
     633                 :             : 
     634   [ +  +  +  + ]:         400 :     switch (type_enum)
     635                 :             :     {
     636                 :          40 :         case ECPGt_struct:
     637                 :             :         case ECPGt_union:
     638                 :             :             /* pointer has to get dimension 0 */
     639         [ +  + ]:          40 :             if (pointer_len)
     640                 :             :             {
     641                 :          10 :                 *length = *dimension;
     642                 :          10 :                 *dimension = "0";
     643                 :             :             }
     644                 :             : 
     645         [ -  + ]:          40 :             if (atoi(*length) >= 0)
     646                 :           0 :                 mmfatal(PARSE_ERROR, "multidimensional arrays for structures are not supported");
     647                 :             : 
     648                 :          40 :             break;
     649                 :          23 :         case ECPGt_varchar:
     650                 :             :         case ECPGt_bytea:
     651                 :             :             /* pointer has to get dimension 0 */
     652         [ -  + ]:          23 :             if (pointer_len)
     653                 :           0 :                 *dimension = "0";
     654                 :             : 
     655                 :             :             /* one index is the string length */
     656         [ +  + ]:          23 :             if (atoi(*length) < 0)
     657                 :             :             {
     658                 :          15 :                 *length = *dimension;
     659                 :          15 :                 *dimension = "-1";
     660                 :             :             }
     661                 :             : 
     662                 :          23 :             break;
     663                 :         134 :         case ECPGt_char:
     664                 :             :         case ECPGt_unsigned_char:
     665                 :             :         case ECPGt_string:
     666                 :             :             /* char ** */
     667         [ +  + ]:         134 :             if (pointer_len == 2)
     668                 :             :             {
     669                 :           8 :                 *length = *dimension = "0";
     670                 :           8 :                 break;
     671                 :             :             }
     672                 :             : 
     673                 :             :             /* pointer has to get length 0 */
     674         [ +  + ]:         126 :             if (pointer_len == 1)
     675                 :          46 :                 *length = "0";
     676                 :             : 
     677                 :             :             /* one index is the string length */
     678         [ +  + ]:         126 :             if (atoi(*length) < 0)
     679                 :             :             {
     680                 :             :                 /*
     681                 :             :                  * make sure we return length = -1 for arrays without given
     682                 :             :                  * bounds
     683                 :             :                  */
     684   [ +  +  +  + ]:          70 :                 if (atoi(*dimension) < 0 && !type_definition)
     685                 :             : 
     686                 :             :                     /*
     687                 :             :                      * do not change this for typedefs since it will be
     688                 :             :                      * changed later on when the variable is defined
     689                 :             :                      */
     690                 :           5 :                     *length = "1";
     691         [ +  + ]:          65 :                 else if (strcmp(*dimension, "0") == 0)
     692                 :           2 :                     *length = "-1";
     693                 :             :                 else
     694                 :          63 :                     *length = *dimension;
     695                 :             : 
     696                 :          70 :                 *dimension = "-1";
     697                 :             :             }
     698                 :         126 :             break;
     699                 :         203 :         default:
     700                 :             :             /* a pointer has dimension = 0 */
     701         [ +  + ]:         203 :             if (pointer_len)
     702                 :             :             {
     703                 :          20 :                 *length = *dimension;
     704                 :          20 :                 *dimension = "0";
     705                 :             :             }
     706                 :             : 
     707         [ -  + ]:         203 :             if (atoi(*length) >= 0)
     708                 :           0 :                 mmfatal(PARSE_ERROR, "multidimensional arrays for simple data types are not supported");
     709                 :             : 
     710                 :         203 :             break;
     711                 :             :     }
     712                 :         400 : }
        

Generated by: LCOV version 2.0-1