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

Generated by: LCOV version 1.14