LCOV - code coverage report
Current view: top level - contrib/seg - segparse.y (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 92.7 % 55 51
Test Date: 2026-03-02 20:14:46 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit

            Line data    Source code
       1              : %{
       2              : /* contrib/seg/segparse.y */
       3              : 
       4              : #include "postgres.h"
       5              : 
       6              : #include <float.h>
       7              : #include <math.h>
       8              : 
       9              : #include "fmgr.h"
      10              : #include "nodes/miscnodes.h"
      11              : #include "utils/builtins.h"
      12              : #include "utils/float.h"
      13              : 
      14              : #include "segdata.h"
      15              : #include "segparse.h"
      16              : 
      17              : /*
      18              :  * Bison doesn't allocate anything that needs to live across parser calls,
      19              :  * so we can easily have it use palloc instead of malloc.  This prevents
      20              :  * memory leaks if we error out during parsing.
      21              :  */
      22              : #define YYMALLOC palloc
      23              : #define YYFREE   pfree
      24              : 
      25              : static bool seg_atof(char *value, float *result, struct Node *escontext);
      26              : 
      27              : static int sig_digits(const char *value);
      28              : 
      29              : %}
      30              : 
      31              : /* BISON Declarations */
      32              : %parse-param {SEG *result}
      33              : %parse-param {struct Node *escontext}
      34              : %parse-param {yyscan_t yyscanner}
      35              : %lex-param   {yyscan_t yyscanner}
      36              : %pure-parser
      37              : %expect 0
      38              : %name-prefix="seg_yy"
      39              : 
      40              : %union
      41              : {
      42              :     struct BND
      43              :     {
      44              :         float       val;
      45              :         char        ext;
      46              :         char        sigd;
      47              :     } bnd;
      48              :     char       *text;
      49              : }
      50              : %token <text> SEGFLOAT
      51              : %token <text> RANGE
      52              : %token <text> PLUMIN
      53              : %token <text> EXTENSION
      54              : %type  <bnd>  boundary
      55              : %type  <bnd>  deviation
      56              : %start range
      57              : 
      58              : /* Grammar follows */
      59              : %%
      60              : 
      61              : 
      62              : range: boundary PLUMIN deviation
      63              :     {
      64              :         char        strbuf[25];
      65              : 
      66            7 :         result->lower = $1.val - $3.val;
      67            7 :         result->upper = $1.val + $3.val;
      68            7 :         snprintf(strbuf, sizeof(strbuf), "%g", result->lower);
      69            7 :         result->l_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd));
      70            7 :         snprintf(strbuf, sizeof(strbuf), "%g", result->upper);
      71            7 :         result->u_sigd = Max(sig_digits(strbuf), Max($1.sigd, $3.sigd));
      72            7 :         result->l_ext = '\0';
      73            7 :         result->u_ext = '\0';
      74              : 
      75              :         (void) yynerrs; /* suppress compiler warning */
      76              :     }
      77              : 
      78              :     | boundary RANGE boundary
      79              :     {
      80         2353 :         result->lower = $1.val;
      81         2353 :         result->upper = $3.val;
      82         2353 :         if ( result->lower > result->upper ) {
      83            0 :             errsave(escontext,
      84              :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      85              :                      errmsg("swapped boundaries: %g is greater than %g",
      86              :                             result->lower, result->upper)));
      87              : 
      88            0 :             YYERROR;
      89              :         }
      90         2353 :         result->l_sigd = $1.sigd;
      91         2353 :         result->u_sigd = $3.sigd;
      92         2353 :         result->l_ext = ( $1.ext ? $1.ext : '\0' );
      93         2353 :         result->u_ext = ( $3.ext ? $3.ext : '\0' );
      94              :     }
      95              : 
      96              :     | boundary RANGE
      97              :     {
      98           46 :         result->lower = $1.val;
      99           46 :         result->upper = HUGE_VAL;
     100           46 :         result->l_sigd = $1.sigd;
     101           46 :         result->u_sigd = 0;
     102           46 :         result->l_ext = ( $1.ext ? $1.ext : '\0' );
     103           46 :         result->u_ext = '-';
     104              :     }
     105              : 
     106              :     | RANGE boundary
     107              :     {
     108           49 :         result->lower = -HUGE_VAL;
     109           49 :         result->upper = $2.val;
     110           49 :         result->l_sigd = 0;
     111           49 :         result->u_sigd = $2.sigd;
     112           49 :         result->l_ext = '-';
     113           49 :         result->u_ext = ( $2.ext ? $2.ext : '\0' );
     114              :     }
     115              : 
     116              :     | boundary
     117              :     {
     118          360 :         result->lower = result->upper = $1.val;
     119          360 :         result->l_sigd = result->u_sigd = $1.sigd;
     120          360 :         result->l_ext = result->u_ext = ( $1.ext ? $1.ext : '\0' );
     121              :     }
     122              :     ;
     123              : 
     124              : boundary: SEGFLOAT
     125              :     {
     126              :         /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
     127              :         float       val;
     128              : 
     129         3954 :         if (!seg_atof($1, &val, escontext))
     130            2 :             YYABORT;
     131              : 
     132         3951 :         $$.ext = '\0';
     133         3951 :         $$.sigd = sig_digits($1);
     134         3951 :         $$.val = val;
     135              :     }
     136              :     | EXTENSION SEGFLOAT
     137              :     {
     138              :         /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
     139              :         float       val;
     140              : 
     141         1217 :         if (!seg_atof($2, &val, escontext))
     142            0 :             YYABORT;
     143              : 
     144         1217 :         $$.ext = $1[0];
     145         1217 :         $$.sigd = sig_digits($2);
     146         1217 :         $$.val = val;
     147              :     }
     148              :     ;
     149              : 
     150              : deviation: SEGFLOAT
     151              :     {
     152              :         /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
     153              :         float       val;
     154              : 
     155            7 :         if (!seg_atof($1, &val, escontext))
     156            0 :             YYABORT;
     157              : 
     158            7 :         $$.ext = '\0';
     159            7 :         $$.sigd = sig_digits($1);
     160            7 :         $$.val = val;
     161              :     }
     162              :     ;
     163              : 
     164              : %%
     165              : 
     166              : 
     167              : static bool
     168         5178 : seg_atof(char *value, float *result, struct Node *escontext)
     169              : {
     170         5178 :     *result = float4in_internal(value, NULL, "seg", value, escontext);
     171         5177 :     if (SOFT_ERROR_OCCURRED(escontext))
     172            2 :         return false;
     173         5175 :     return true;
     174              : }
     175              : 
     176              : static int
     177         5191 : sig_digits(const char *value)
     178              : {
     179         5191 :     int         n = significant_digits(value);
     180              : 
     181              :     /* Clamp, to ensure value will fit in sigd fields */
     182         5191 :     return Min(n, FLT_DIG);
     183              : }
        

Generated by: LCOV version 2.0-1