LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/preproc - util.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 96.8 % 94 91
Test Date: 2026-07-12 22:15:32 Functions: 100.0 % 12 12
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 73.3 % 30 22

             Branch data     Line data    Source code
       1                 :             : /* src/interfaces/ecpg/preproc/util.c */
       2                 :             : 
       3                 :             : #include "postgres_fe.h"
       4                 :             : 
       5                 :             : #include <unistd.h>
       6                 :             : 
       7                 :             : #include "preproc_extern.h"
       8                 :             : 
       9                 :             : static void vmmerror(int error_code, enum errortype type, const char *error, va_list ap) pg_attribute_printf(3, 0);
      10                 :             : 
      11                 :             : 
      12                 :             : /*
      13                 :             :  * Handle preprocessor errors and warnings
      14                 :             :  */
      15                 :             : static void
      16                 :          17 : vmmerror(int error_code, enum errortype type, const char *error, va_list ap)
      17                 :             : {
      18                 :             :     /* localize the error message string */
      19                 :          17 :     error = _(error);
      20                 :             : 
      21                 :          17 :     fprintf(stderr, "%s:%d: ", input_filename, base_yylineno);
      22                 :             : 
      23      [ +  +  - ]:          17 :     switch (type)
      24                 :             :     {
      25                 :           6 :         case ET_WARNING:
      26                 :           6 :             fprintf(stderr, _("WARNING: "));
      27                 :           6 :             break;
      28                 :          11 :         case ET_ERROR:
      29                 :          11 :             fprintf(stderr, _("ERROR: "));
      30                 :          11 :             break;
      31                 :             :     }
      32                 :             : 
      33                 :          17 :     vfprintf(stderr, error, ap);
      34                 :             : 
      35                 :          17 :     fprintf(stderr, "\n");
      36                 :             : 
      37                 :             :     /* If appropriate, set error code to be inspected by ecpg.c */
      38      [ +  +  - ]:          17 :     switch (type)
      39                 :             :     {
      40                 :           6 :         case ET_WARNING:
      41                 :           6 :             break;
      42                 :          11 :         case ET_ERROR:
      43                 :          11 :             ret_value = error_code;
      44                 :          11 :             break;
      45                 :             :     }
      46                 :          17 : }
      47                 :             : 
      48                 :             : /* Report an error or warning */
      49                 :             : void
      50                 :          16 : mmerror(int error_code, enum errortype type, const char *error, ...)
      51                 :             : {
      52                 :             :     va_list     ap;
      53                 :             : 
      54                 :          16 :     va_start(ap, error);
      55                 :          16 :     vmmerror(error_code, type, error, ap);
      56                 :          16 :     va_end(ap);
      57                 :          16 : }
      58                 :             : 
      59                 :             : /* Report an error and abandon execution */
      60                 :             : void
      61                 :           1 : mmfatal(int error_code, const char *error, ...)
      62                 :             : {
      63                 :             :     va_list     ap;
      64                 :             : 
      65                 :           1 :     va_start(ap, error);
      66                 :           1 :     vmmerror(error_code, ET_ERROR, error, ap);
      67                 :           1 :     va_end(ap);
      68                 :             : 
      69         [ +  - ]:           1 :     if (base_yyin)
      70                 :           1 :         fclose(base_yyin);
      71         [ +  - ]:           1 :     if (base_yyout)
      72                 :           1 :         fclose(base_yyout);
      73                 :             : 
      74   [ +  -  -  + ]:           1 :     if (strcmp(output_filename, "-") != 0 && unlink(output_filename) != 0)
      75                 :           0 :         fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename);
      76                 :           1 :     exit(error_code);
      77                 :             : }
      78                 :             : 
      79                 :             : /*
      80                 :             :  * Basic memory management support
      81                 :             :  */
      82                 :             : 
      83                 :             : /* malloc + error check */
      84                 :             : void *
      85                 :       29448 : mm_alloc(size_t size)
      86                 :             : {
      87                 :       29448 :     void       *ptr = malloc(size);
      88                 :             : 
      89         [ -  + ]:       29448 :     if (ptr == NULL)
      90                 :           0 :         mmfatal(OUT_OF_MEMORY, "out of memory");
      91                 :             : 
      92                 :       29448 :     return ptr;
      93                 :             : }
      94                 :             : 
      95                 :             : /* strdup + error check */
      96                 :             : char *
      97                 :        6554 : mm_strdup(const char *string)
      98                 :             : {
      99                 :        6554 :     char       *new = strdup(string);
     100                 :             : 
     101         [ -  + ]:        6554 :     if (new == NULL)
     102                 :           0 :         mmfatal(OUT_OF_MEMORY, "out of memory");
     103                 :             : 
     104                 :        6554 :     return new;
     105                 :             : }
     106                 :             : 
     107                 :             : 
     108                 :             : /*
     109                 :             :  * "Local" memory management support
     110                 :             :  *
     111                 :             :  * These functions manage memory that is only needed for a short time
     112                 :             :  * (processing of one input statement) within the ecpg grammar.
     113                 :             :  * Data allocated with these is not meant to be freed separately;
     114                 :             :  * rather it's freed by calling reclaim_local_storage() at the end
     115                 :             :  * of each statement cycle.
     116                 :             :  */
     117                 :             : 
     118                 :             : typedef struct loc_chunk
     119                 :             : {
     120                 :             :     struct loc_chunk *next;     /* list link */
     121                 :             :     unsigned int chunk_used;    /* index of first unused byte in data[] */
     122                 :             :     unsigned int chunk_avail;   /* # bytes still available in data[] */
     123                 :             :     char        data[FLEXIBLE_ARRAY_MEMBER];    /* actual storage */
     124                 :             : } loc_chunk;
     125                 :             : 
     126                 :             : #define LOC_CHUNK_OVERHEAD  MAXALIGN(offsetof(loc_chunk, data))
     127                 :             : #define LOC_CHUNK_MIN_SIZE  8192
     128                 :             : 
     129                 :             : /* Head of list of loc_chunks */
     130                 :             : static loc_chunk *loc_chunks = NULL;
     131                 :             : 
     132                 :             : /*
     133                 :             :  * Allocate local space of the requested size.
     134                 :             :  *
     135                 :             :  * Exits on OOM.
     136                 :             :  */
     137                 :             : void *
     138                 :       92158 : loc_alloc(size_t size)
     139                 :             : {
     140                 :             :     void       *result;
     141                 :       92158 :     loc_chunk  *cur_chunk = loc_chunks;
     142                 :             : 
     143                 :             :     /* Ensure all allocations are adequately aligned */
     144                 :       92158 :     size = MAXALIGN(size);
     145                 :             : 
     146                 :             :     /* Need a new chunk? */
     147   [ +  +  +  + ]:       92158 :     if (cur_chunk == NULL || size > cur_chunk->chunk_avail)
     148                 :             :     {
     149                 :       24563 :         size_t      chunk_size = Max(size, LOC_CHUNK_MIN_SIZE);
     150                 :             : 
     151                 :       24563 :         cur_chunk = mm_alloc(chunk_size + LOC_CHUNK_OVERHEAD);
     152                 :             :         /* Depending on alignment rules, we could waste a bit here */
     153                 :       24563 :         cur_chunk->chunk_used = LOC_CHUNK_OVERHEAD - offsetof(loc_chunk, data);
     154                 :       24563 :         cur_chunk->chunk_avail = chunk_size;
     155                 :             :         /* New chunk becomes the head of the list */
     156                 :       24563 :         cur_chunk->next = loc_chunks;
     157                 :       24563 :         loc_chunks = cur_chunk;
     158                 :             :     }
     159                 :             : 
     160                 :       92158 :     result = cur_chunk->data + cur_chunk->chunk_used;
     161                 :       92158 :     cur_chunk->chunk_used += size;
     162                 :       92158 :     cur_chunk->chunk_avail -= size;
     163                 :       92158 :     return result;
     164                 :             : }
     165                 :             : 
     166                 :             : /*
     167                 :             :  * Copy given string into local storage
     168                 :             :  */
     169                 :             : char *
     170                 :       49727 : loc_strdup(const char *string)
     171                 :             : {
     172                 :       49727 :     char       *result = loc_alloc(strlen(string) + 1);
     173                 :             : 
     174                 :       49727 :     strcpy(result, string);
     175                 :       49727 :     return result;
     176                 :             : }
     177                 :             : 
     178                 :             : /*
     179                 :             :  * Reclaim local storage when appropriate
     180                 :             :  */
     181                 :             : void
     182                 :       24480 : reclaim_local_storage(void)
     183                 :             : {
     184                 :             :     loc_chunk  *cur_chunk,
     185                 :             :                *next_chunk;
     186                 :             : 
     187         [ +  + ]:       48973 :     for (cur_chunk = loc_chunks; cur_chunk; cur_chunk = next_chunk)
     188                 :             :     {
     189                 :       24493 :         next_chunk = cur_chunk->next;
     190                 :       24493 :         free(cur_chunk);
     191                 :             :     }
     192                 :       24480 :     loc_chunks = NULL;
     193                 :       24480 : }
     194                 :             : 
     195                 :             : 
     196                 :             : /*
     197                 :             :  * String concatenation support routines.  These return "local" (transient)
     198                 :             :  * storage.
     199                 :             :  */
     200                 :             : 
     201                 :             : /*
     202                 :             :  * Concatenate 2 strings, inserting a space between them unless either is empty
     203                 :             :  */
     204                 :             : char *
     205                 :        5114 : cat2_str(const char *str1, const char *str2)
     206                 :             : {
     207                 :        5114 :     char       *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + 2);
     208                 :             : 
     209                 :        5114 :     strcpy(res_str, str1);
     210   [ +  +  +  + ]:        5114 :     if (strlen(str1) != 0 && strlen(str2) != 0)
     211                 :        3290 :         strcat(res_str, " ");
     212                 :        5114 :     strcat(res_str, str2);
     213                 :        5114 :     return res_str;
     214                 :             : }
     215                 :             : 
     216                 :             : /*
     217                 :             :  * Concatenate N strings, inserting spaces between them unless they are empty
     218                 :             :  */
     219                 :             : char *
     220                 :        1518 : cat_str(int count, ...)
     221                 :             : {
     222                 :             :     va_list     args;
     223                 :             :     int         i;
     224                 :             :     char       *res_str;
     225                 :             : 
     226                 :        1518 :     va_start(args, count);
     227                 :             : 
     228                 :        1518 :     res_str = va_arg(args, char *);
     229                 :             : 
     230                 :             :     /* now add all other strings */
     231         [ +  + ]:        6300 :     for (i = 1; i < count; i++)
     232                 :        4782 :         res_str = cat2_str(res_str, va_arg(args, char *));
     233                 :             : 
     234                 :        1518 :     va_end(args);
     235                 :             : 
     236                 :        1518 :     return res_str;
     237                 :             : }
     238                 :             : 
     239                 :             : /*
     240                 :             :  * Concatenate 2 strings, with no space between
     241                 :             :  */
     242                 :             : char *
     243                 :          50 : make2_str(const char *str1, const char *str2)
     244                 :             : {
     245                 :          50 :     char       *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + 1);
     246                 :             : 
     247                 :          50 :     strcpy(res_str, str1);
     248                 :          50 :     strcat(res_str, str2);
     249                 :          50 :     return res_str;
     250                 :             : }
     251                 :             : 
     252                 :             : /*
     253                 :             :  * Concatenate 3 strings, with no space between
     254                 :             :  */
     255                 :             : char *
     256                 :        1891 : make3_str(const char *str1, const char *str2, const char *str3)
     257                 :             : {
     258                 :        1891 :     char       *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + strlen(str3) + 1);
     259                 :             : 
     260                 :        1891 :     strcpy(res_str, str1);
     261                 :        1891 :     strcat(res_str, str2);
     262                 :        1891 :     strcat(res_str, str3);
     263                 :        1891 :     return res_str;
     264                 :             : }
        

Generated by: LCOV version 2.0-1