LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/preproc - util.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 57 94 60.6 %
Date: 2024-11-21 09:14:53 Functions: 9 12 75.0 %
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           0 : vmmerror(int error_code, enum errortype type, const char *error, va_list ap)
      17             : {
      18             :     /* localize the error message string */
      19           0 :     error = _(error);
      20             : 
      21           0 :     fprintf(stderr, "%s:%d: ", input_filename, base_yylineno);
      22             : 
      23           0 :     switch (type)
      24             :     {
      25           0 :         case ET_WARNING:
      26           0 :             fprintf(stderr, _("WARNING: "));
      27           0 :             break;
      28           0 :         case ET_ERROR:
      29           0 :             fprintf(stderr, _("ERROR: "));
      30           0 :             break;
      31             :     }
      32             : 
      33           0 :     vfprintf(stderr, error, ap);
      34             : 
      35           0 :     fprintf(stderr, "\n");
      36             : 
      37             :     /* If appropriate, set error code to be inspected by ecpg.c */
      38           0 :     switch (type)
      39             :     {
      40           0 :         case ET_WARNING:
      41           0 :             break;
      42           0 :         case ET_ERROR:
      43           0 :             ret_value = error_code;
      44           0 :             break;
      45             :     }
      46           0 : }
      47             : 
      48             : /* Report an error or warning */
      49             : void
      50           0 : mmerror(int error_code, enum errortype type, const char *error,...)
      51             : {
      52             :     va_list     ap;
      53             : 
      54           0 :     va_start(ap, error);
      55           0 :     vmmerror(error_code, type, error, ap);
      56           0 :     va_end(ap);
      57           0 : }
      58             : 
      59             : /* Report an error and abandon execution */
      60             : void
      61           0 : mmfatal(int error_code, const char *error,...)
      62             : {
      63             :     va_list     ap;
      64             : 
      65           0 :     va_start(ap, error);
      66           0 :     vmmerror(error_code, ET_ERROR, error, ap);
      67           0 :     va_end(ap);
      68             : 
      69           0 :     if (base_yyin)
      70           0 :         fclose(base_yyin);
      71           0 :     if (base_yyout)
      72           0 :         fclose(base_yyout);
      73             : 
      74           0 :     if (strcmp(output_filename, "-") != 0 && unlink(output_filename) != 0)
      75           0 :         fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename);
      76           0 :     exit(error_code);
      77             : }
      78             : 
      79             : /*
      80             :  * Basic memory management support
      81             :  */
      82             : 
      83             : /* malloc + error check */
      84             : void *
      85       57016 : mm_alloc(size_t size)
      86             : {
      87       57016 :     void       *ptr = malloc(size);
      88             : 
      89       57016 :     if (ptr == NULL)
      90           0 :         mmfatal(OUT_OF_MEMORY, "out of memory");
      91             : 
      92       57016 :     return ptr;
      93             : }
      94             : 
      95             : /* strdup + error check */
      96             : char *
      97       37990 : mm_strdup(const char *string)
      98             : {
      99       37990 :     char       *new = strdup(string);
     100             : 
     101       37990 :     if (new == NULL)
     102           0 :         mmfatal(OUT_OF_MEMORY, "out of memory");
     103             : 
     104       37990 :     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      152664 : loc_alloc(size_t size)
     139             : {
     140             :     void       *result;
     141      152664 :     loc_chunk  *cur_chunk = loc_chunks;
     142             : 
     143             :     /* Ensure all allocations are adequately aligned */
     144      152664 :     size = MAXALIGN(size);
     145             : 
     146             :     /* Need a new chunk? */
     147      152664 :     if (cur_chunk == NULL || size > cur_chunk->chunk_avail)
     148             :     {
     149       47906 :         size_t      chunk_size = Max(size, LOC_CHUNK_MIN_SIZE);
     150             : 
     151       47906 :         cur_chunk = mm_alloc(chunk_size + LOC_CHUNK_OVERHEAD);
     152             :         /* Depending on alignment rules, we could waste a bit here */
     153       47906 :         cur_chunk->chunk_used = LOC_CHUNK_OVERHEAD - offsetof(loc_chunk, data);
     154       47906 :         cur_chunk->chunk_avail = chunk_size;
     155             :         /* New chunk becomes the head of the list */
     156       47906 :         cur_chunk->next = loc_chunks;
     157       47906 :         loc_chunks = cur_chunk;
     158             :     }
     159             : 
     160      152664 :     result = cur_chunk->data + cur_chunk->chunk_used;
     161      152664 :     cur_chunk->chunk_used += size;
     162      152664 :     cur_chunk->chunk_avail -= size;
     163      152664 :     return result;
     164             : }
     165             : 
     166             : /*
     167             :  * Copy given string into local storage
     168             :  */
     169             : char *
     170       71700 : loc_strdup(const char *string)
     171             : {
     172       71700 :     char       *result = loc_alloc(strlen(string) + 1);
     173             : 
     174       71700 :     strcpy(result, string);
     175       71700 :     return result;
     176             : }
     177             : 
     178             : /*
     179             :  * Reclaim local storage when appropriate
     180             :  */
     181             : void
     182       47748 : reclaim_local_storage(void)
     183             : {
     184             :     loc_chunk  *cur_chunk,
     185             :                *next_chunk;
     186             : 
     187       95522 :     for (cur_chunk = loc_chunks; cur_chunk; cur_chunk = next_chunk)
     188             :     {
     189       47774 :         next_chunk = cur_chunk->next;
     190       47774 :         free(cur_chunk);
     191             :     }
     192       47748 :     loc_chunks = NULL;
     193       47748 : }
     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        9570 : cat2_str(const char *str1, const char *str2)
     206             : {
     207        9570 :     char       *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + 2);
     208             : 
     209        9570 :     strcpy(res_str, str1);
     210        9570 :     if (strlen(str1) != 0 && strlen(str2) != 0)
     211        6158 :         strcat(res_str, " ");
     212        9570 :     strcat(res_str, str2);
     213        9570 :     return res_str;
     214             : }
     215             : 
     216             : /*
     217             :  * Concatenate N strings, inserting spaces between them unless they are empty
     218             :  */
     219             : char *
     220        2844 : cat_str(int count,...)
     221             : {
     222             :     va_list     args;
     223             :     int         i;
     224             :     char       *res_str;
     225             : 
     226        2844 :     va_start(args, count);
     227             : 
     228        2844 :     res_str = va_arg(args, char *);
     229             : 
     230             :     /* now add all other strings */
     231       11784 :     for (i = 1; i < count; i++)
     232        8940 :         res_str = cat2_str(res_str, va_arg(args, char *));
     233             : 
     234        2844 :     va_end(args);
     235             : 
     236        2844 :     return res_str;
     237             : }
     238             : 
     239             : /*
     240             :  * Concatenate 2 strings, with no space between
     241             :  */
     242             : char *
     243         100 : make2_str(const char *str1, const char *str2)
     244             : {
     245         100 :     char       *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + 1);
     246             : 
     247         100 :     strcpy(res_str, str1);
     248         100 :     strcat(res_str, str2);
     249         100 :     return res_str;
     250             : }
     251             : 
     252             : /*
     253             :  * Concatenate 3 strings, with no space between
     254             :  */
     255             : char *
     256        3296 : make3_str(const char *str1, const char *str2, const char *str3)
     257             : {
     258        3296 :     char       *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + strlen(str3) + 1);
     259             : 
     260        3296 :     strcpy(res_str, str1);
     261        3296 :     strcat(res_str, str2);
     262        3296 :     strcat(res_str, str3);
     263        3296 :     return res_str;
     264             : }

Generated by: LCOV version 1.14