LCOV - code coverage report
Current view: top level - contrib/seg - segparse.y (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 92.7 % 55 51
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 70.0 % 20 14

             Branch data     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                 :        2360 :         result->lower = $1.val;
      81                 :        2360 :         result->upper = $3.val;
      82         [ -  + ]:        2360 :         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                 :        2360 :         result->l_sigd = $1.sigd;
      91                 :        2360 :         result->u_sigd = $3.sigd;
      92                 :        2360 :         result->l_ext = ( $1.ext ? $1.ext : '\0' );
      93                 :        2360 :         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         [ +  + ]:        3960 :         if (!seg_atof($1, &val, escontext))
     130                 :           2 :             YYABORT;
     131                 :             : 
     132                 :        3957 :         $$.ext = '\0';
     133                 :        3957 :         $$.sigd = sig_digits($1);
     134                 :        3957 :         $$.val = val;
     135                 :             :     }
     136                 :             :     | EXTENSION SEGFLOAT
     137                 :             :     {
     138                 :             :         /* temp variable avoids a gcc 3.3.x bug on Sparc64 */
     139                 :             :         float       val;
     140                 :             : 
     141         [ -  + ]:        1225 :         if (!seg_atof($2, &val, escontext))
     142                 :           0 :             YYABORT;
     143                 :             : 
     144                 :        1225 :         $$.ext = $1[0];
     145                 :        1225 :         $$.sigd = sig_digits($2);
     146                 :        1225 :         $$.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                 :        5192 : seg_atof(char *value, float *result, struct Node *escontext)
     169                 :             : {
     170                 :        5192 :     *result = float4in_internal(value, NULL, "seg", value, escontext);
     171   [ +  +  +  -  :        5191 :     if (SOFT_ERROR_OCCURRED(escontext))
                   +  + ]
     172                 :           2 :         return false;
     173                 :        5189 :     return true;
     174                 :             : }
     175                 :             : 
     176                 :             : static int
     177                 :        5205 : sig_digits(const char *value)
     178                 :             : {
     179                 :        5205 :     int         n = significant_digits(value);
     180                 :             : 
     181                 :             :     /* Clamp, to ensure value will fit in sigd fields */
     182                 :        5205 :     return Min(n, FLT_DIG);
     183                 :             : }
        

Generated by: LCOV version 2.0-1