LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/preproc - util.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 96.8 % 94 91
Test Date: 2026-03-03 13:15:30 Functions: 100.0 % 12 12
Legend: Lines:     hit not hit

            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        29038 : mm_alloc(size_t size)
      86              : {
      87        29038 :     void       *ptr = malloc(size);
      88              : 
      89        29038 :     if (ptr == NULL)
      90            0 :         mmfatal(OUT_OF_MEMORY, "out of memory");
      91              : 
      92        29038 :     return ptr;
      93              : }
      94              : 
      95              : /* strdup + error check */
      96              : char *
      97         6411 : mm_strdup(const char *string)
      98              : {
      99         6411 :     char       *new = strdup(string);
     100              : 
     101         6411 :     if (new == NULL)
     102            0 :         mmfatal(OUT_OF_MEMORY, "out of memory");
     103              : 
     104         6411 :     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        90082 : loc_alloc(size_t size)
     139              : {
     140              :     void       *result;
     141        90082 :     loc_chunk  *cur_chunk = loc_chunks;
     142              : 
     143              :     /* Ensure all allocations are adequately aligned */
     144        90082 :     size = MAXALIGN(size);
     145              : 
     146              :     /* Need a new chunk? */
     147        90082 :     if (cur_chunk == NULL || size > cur_chunk->chunk_avail)
     148              :     {
     149        24258 :         size_t      chunk_size = Max(size, LOC_CHUNK_MIN_SIZE);
     150              : 
     151        24258 :         cur_chunk = mm_alloc(chunk_size + LOC_CHUNK_OVERHEAD);
     152              :         /* Depending on alignment rules, we could waste a bit here */
     153        24258 :         cur_chunk->chunk_used = LOC_CHUNK_OVERHEAD - offsetof(loc_chunk, data);
     154        24258 :         cur_chunk->chunk_avail = chunk_size;
     155              :         /* New chunk becomes the head of the list */
     156        24258 :         cur_chunk->next = loc_chunks;
     157        24258 :         loc_chunks = cur_chunk;
     158              :     }
     159              : 
     160        90082 :     result = cur_chunk->data + cur_chunk->chunk_used;
     161        90082 :     cur_chunk->chunk_used += size;
     162        90082 :     cur_chunk->chunk_avail -= size;
     163        90082 :     return result;
     164              : }
     165              : 
     166              : /*
     167              :  * Copy given string into local storage
     168              :  */
     169              : char *
     170        48547 : loc_strdup(const char *string)
     171              : {
     172        48547 :     char       *result = loc_alloc(strlen(string) + 1);
     173              : 
     174        48547 :     strcpy(result, string);
     175        48547 :     return result;
     176              : }
     177              : 
     178              : /*
     179              :  * Reclaim local storage when appropriate
     180              :  */
     181              : void
     182        24177 : reclaim_local_storage(void)
     183              : {
     184              :     loc_chunk  *cur_chunk,
     185              :                *next_chunk;
     186              : 
     187        48367 :     for (cur_chunk = loc_chunks; cur_chunk; cur_chunk = next_chunk)
     188              :     {
     189        24190 :         next_chunk = cur_chunk->next;
     190        24190 :         free(cur_chunk);
     191              :     }
     192        24177 :     loc_chunks = NULL;
     193        24177 : }
     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         5000 : cat2_str(const char *str1, const char *str2)
     206              : {
     207         5000 :     char       *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + 2);
     208              : 
     209         5000 :     strcpy(res_str, str1);
     210         5000 :     if (strlen(str1) != 0 && strlen(str2) != 0)
     211         3221 :         strcat(res_str, " ");
     212         5000 :     strcat(res_str, str2);
     213         5000 :     return res_str;
     214              : }
     215              : 
     216              : /*
     217              :  * Concatenate N strings, inserting spaces between them unless they are empty
     218              :  */
     219              : char *
     220         1486 : cat_str(int count,...)
     221              : {
     222              :     va_list     args;
     223              :     int         i;
     224              :     char       *res_str;
     225              : 
     226         1486 :     va_start(args, count);
     227              : 
     228         1486 :     res_str = va_arg(args, char *);
     229              : 
     230              :     /* now add all other strings */
     231         6166 :     for (i = 1; i < count; i++)
     232         4680 :         res_str = cat2_str(res_str, va_arg(args, char *));
     233              : 
     234         1486 :     va_end(args);
     235              : 
     236         1486 :     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         1845 : make3_str(const char *str1, const char *str2, const char *str3)
     257              : {
     258         1845 :     char       *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + strlen(str3) + 1);
     259              : 
     260         1845 :     strcpy(res_str, str1);
     261         1845 :     strcat(res_str, str2);
     262         1845 :     strcat(res_str, str3);
     263         1845 :     return res_str;
     264              : }
        

Generated by: LCOV version 2.0-1