"Fossies" - the Fresh Open Source Software Archive

Member "udunits-2.2.28/lib/scanner.l" (23 Nov 2020, 8139 Bytes) of package /linux/privat/udunits-2.2.28.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "scanner.l": 2.2.26_vs_2.2.28.

    1 /*
    2  * Copyright 2014 University Corporation for Atmospheric Research
    3  *
    4  * This file is part of the UDUNITS-2 package.  See the file COPYRIGHT
    5  * in the top-level source-directory of the package for copying and
    6  * redistribution conditions.
    7  */
    8 /*
    9  * lex(1) specification for tokens for the Unidata units package, UDUNITS2.
   10  */
   11 
   12 %option noyywrap
   13 
   14 %{
   15 
   16 #include <ctype.h>
   17 #include <errno.h>
   18 #include <limits.h>
   19 #include <math.h>
   20 #include <stddef.h>
   21 #include <stdio.h>
   22 #include <stdlib.h>
   23 #include <string.h>
   24 #include <time.h>
   25 
   26 /**
   27  * Decodes a date.
   28  *
   29  * @param[in]  text     The text specifying the date to be decoded.
   30  * @param[in]  format   The format to use for decoding. The order is year (int),
   31  *                      month (int), and day (int).
   32  * @param[out] date     The date corresponding to the input.
   33  * @retval     DATE     Success
   34  * @retval     ERR      Error
   35  */
   36 static int decodeDate(
   37     const char* const   text,
   38     const char* const   format,
   39     double* const       date)
   40 {
   41     int     year;
   42     int     month = 1;
   43     int     day = 1;
   44 
   45     (void)sscanf(text, format, &year, &month, &day);
   46     *date = ut_encode_date(year, month, day);
   47     return DATE;
   48 }
   49 
   50 /**
   51  * Decodes a clock-time.
   52  *
   53  * @param[in] text      The text specifying the clock-time to be decoded.
   54  * @param[in] format    The format to use for decoding. The order is hour (int),
   55  *                      minute (int), and second (double).
   56  * @return              The clock-time corresponding to the input.
   57  */
   58 static double decodeClock(
   59     const char* const   text,
   60     const char* const   format)
   61 {
   62     int         hour = 0;
   63     int         minute = 0;
   64     double      second = 0;
   65 
   66     (void)sscanf(text, format, &hour, &minute, &second);
   67     if (hour < 0) {
   68         minute = -minute;
   69         second = -second;
   70     }
   71     return ut_encode_clock(hour, minute, second);
   72 }
   73 
   74 /**
   75  * Decodes a real value.
   76  *
   77  * @param[in]  text     Text to be decoded.
   78  * @param[out] value    Decoded value.
   79  * @retval     REAL     Success.
   80  * @retval     ERR      Failure.
   81  */
   82 static int decodeReal(
   83     const char* const text,
   84     double* const     value)
   85 {
   86     errno = 0;
   87     *value = strtod(text, NULL);
   88 
   89     if (errno == 0)
   90         return REAL;
   91 
   92     ut_handle_error_message("Invalid real: \"%s\"", text);
   93     return ERR;
   94 }
   95 
   96 %}
   97 
   98 space           [ \t\r\f\v]
   99 sign                    [+-]
  100 int         [0-9]+
  101 int_period      {int}\.
  102 period_int      \.{int}
  103 int_period_int      {int}\.{int}
  104 mantissa        {int_period}|{period_int}|{int_period_int}
  105 real_exp        [eE][+-]?[0-9]+
  106 real            [+-]?({int}{real_exp}|{mantissa}{real_exp}?)
  107 year            [+-]?[0-9]{1,4}
  108 month           0?[1-9]|1[0-2]
  109 day         0?[1-9]|[1-2][0-9]|30|31
  110 hour            [+-]?[0-1]?[0-9]|2[0-3]
  111 minute          [0-5]?[0-9]
  112 second          ({minute}|60)(\.[0-9]*)?
  113 middot                  \xc2\xb7
  114 utf8_exp_digit          \xc2(\xb9|\xb2|\xb3)|\xe2\x81(\xb0|[\xb4-\xb9])
  115 utf8_exp_sign       \xe2\x81\xba|\xe2\x81\xbb
  116 utf8_exponent       {utf8_exp_sign}?{utf8_exp_digit}+
  117 nbsp                    \xc2\xa0
  118 shy                     \xc2\xad
  119 degree                  \xc2\xb0
  120 mu                      \xc2\xb5
  121 blk1                    \xc3([\x80-\x96])
  122 blk2                    \xc3([\x98-\xB6])
  123 blk3                    \xc3([\xB8-\xBF])
  124 latin1              {nbsp}|{shy}|{degree}|{mu}|{blk1}|{blk2}|{blk3}
  125 utf8_cont               [\x80-\xbf]
  126 utf8_2bytes             [\xc8-\xdf]{utf8_cont}
  127 utf8_3bytes             [\xe0-\xef]{utf8_cont}{utf8_cont}
  128 letter          [_a-zA-Z]|{latin1}|{utf8_2bytes}|{utf8_3bytes}
  129 alphanum        {letter}|[0-9]
  130 id          %|'|\"|{letter}({alphanum}*{letter})?
  131 broken_date     {year}-{month}(-{day})?
  132 packed_date     {year}({month}{day}?)?
  133 broken_clock        {hour}:{minute}(:{second})?
  134 packed_clock        {hour}({minute}{second}?)?
  135 broken_timestamp    {broken_date}({space}+{broken_clock})?
  136 packed_timestamp    {packed_date}T{packed_clock}?
  137 logref          \({space}*[Rr][Ee](:{space})?{space}*
  138 after                   [Aa][Ff][Tt][Ee][Rr]
  139 from                    [Ff][Rr][Oo][Mm]
  140 since                   [Ss][Ii][Nn][Cc][Ee]
  141 ref                     [Rr][Ee][Ff]
  142 per                     [Pp][Ee][Rr]
  143 
  144 %Start      ID_SEEN SHIFT_SEEN DATE_SEEN CLOCK_SEEN
  145 
  146 %%
  147     if (_restartScanner) {
  148     BEGIN INITIAL;
  149     _restartScanner = 0;
  150     }
  151 
  152 <INITIAL,ID_SEEN>{space}*(@|{after}|{from}|{ref}|{since}){space}* {
  153     BEGIN SHIFT_SEEN;
  154     return SHIFT;
  155 }
  156 
  157 <INITIAL,ID_SEEN>{space}*({per}|"/"){space}* {
  158     BEGIN INITIAL;
  159     return DIVIDE;
  160 }
  161 
  162 <INITIAL,ID_SEEN>"-"|"."|"*"|{middot}|{space}+ {
  163     BEGIN INITIAL;
  164     return MULTIPLY;
  165 }
  166 
  167 <INITIAL,ID_SEEN>("^"|"**")[+-]?{int} {
  168     int     status;
  169 
  170     if (sscanf(yytext, "%*[*^]%ld", &yylval.ival) != 1) {
  171         ut_handle_error_message("Invalid integer\n", stderr);
  172 
  173     status  = ERR;
  174     }
  175     else {
  176     status  = EXPONENT;
  177     }
  178 
  179     return status;
  180 }
  181 
  182 <INITIAL,ID_SEEN>{utf8_exponent} {
  183     int     status = EXPONENT;
  184     int     exponent = 0;
  185     int     sign = 1;
  186     char*   cp = yytext;
  187 
  188     if (strncmp(cp, "\xe2\x81\xba", 3) == 0) {
  189     cp += 3;
  190     }
  191     else if (strncmp(cp, "\xe2\x81\xbb", 3) == 0) {
  192     sign = -1;
  193     cp += 3;
  194     }
  195 
  196     while (cp < yytext + yyleng) {
  197     int j;
  198     static struct {
  199         const char* string;
  200         const int   len;
  201     } utf8_exponents[] = {
  202         {"\xe2\x81\xb0", 3},        /* 0 */
  203         {"\xc2\xb9",     2},        /* 1 */
  204         {"\xc2\xb2",     2},        /* 2 */
  205         {"\xc2\xb3",     2},        /* 3 */
  206         {"\xe2\x81\xb4", 3},        /* 4 */
  207         {"\xe2\x81\xb5", 3},        /* 5 */
  208         {"\xe2\x81\xb6", 3},        /* 6 */
  209         {"\xe2\x81\xb7", 3},        /* 7 */
  210         {"\xe2\x81\xb8", 3},        /* 8 */
  211         {"\xe2\x81\xb9", 3},        /* 9 */
  212     };
  213 
  214         if (exponent > INT_MAX/10) {
  215             status = ERR;
  216             break;
  217         }
  218 
  219     exponent *= 10;
  220 
  221     for (j = 0; j < 10; j++) {
  222         int len = utf8_exponents[j].len;
  223 
  224         if (strncmp(cp, utf8_exponents[j].string, len) == 0) {
  225         exponent += j;
  226         cp += len;
  227         break;
  228         }
  229     }
  230 
  231     if (j >= 10) {
  232         status = ERR;
  233         break;
  234     }
  235     }
  236 
  237     if (status == EXPONENT)
  238     yylval.ival = sign * exponent;
  239 
  240     BEGIN INITIAL;
  241     return status;
  242 }
  243 
  244 <SHIFT_SEEN>{broken_date}(T|{space}*) {
  245     BEGIN DATE_SEEN;
  246     return decodeDate((char*)yytext, "%d-%d-%d", &yylval.rval);
  247 }
  248 
  249 <SHIFT_SEEN>{packed_date}(T|{space}*) {
  250     if (_isTime) {
  251         BEGIN DATE_SEEN;
  252         return decodeDate((char*)yytext, "%4d%2d%2d", &yylval.rval);
  253     }
  254     else {
  255         BEGIN INITIAL;
  256         return decodeReal((char*)yytext, &yylval.rval);
  257     }
  258 }
  259 
  260 <DATE_SEEN>{broken_clock}{space}* {
  261     yylval.rval = decodeClock((char*)yytext, "%d:%d:%lf");
  262     BEGIN CLOCK_SEEN;
  263     return CLOCK;
  264 }
  265 
  266 <DATE_SEEN>{packed_clock}{space}* {
  267     yylval.rval = decodeClock((char*)yytext, "%2d%2d%lf");
  268     BEGIN CLOCK_SEEN;
  269     return CLOCK;
  270 }
  271 
  272 <CLOCK_SEEN>{sign}?{int}:{int} {
  273     yylval.rval = decodeClock((char*)yytext, "%d:%d");
  274     BEGIN INITIAL;
  275     return CLOCK;
  276 }
  277 
  278 <CLOCK_SEEN>{sign}{int} {
  279     yylval.rval = (yyleng <= 3)
  280                         ? decodeClock((char*)yytext, "%d")
  281                         : (yyleng == 4)
  282                             ? decodeClock((char*)yytext, "%2d%d")
  283                             : decodeClock((char*)yytext, "%3d%d");
  284     BEGIN INITIAL;
  285     return CLOCK;
  286 }
  287 
  288 <CLOCK_SEEN>{int} {
  289     yylval.rval = (yyleng <= 2)
  290                         ? decodeClock((char*)yytext, "%d")
  291                         : (yyleng == 3)
  292                             ? decodeClock((char*)yytext, "%1d%d")
  293                             : decodeClock((char*)yytext, "%2d%d");
  294     BEGIN INITIAL;
  295     return CLOCK;
  296 }
  297 
  298 <INITIAL,SHIFT_SEEN>{real} {
  299     BEGIN INITIAL;
  300     return decodeReal((char*)yytext, &yylval.rval);
  301 }
  302 
  303 <INITIAL,ID_SEEN,SHIFT_SEEN>[+-]?{int} {
  304     int     status;
  305 
  306     errno   = 0;
  307     yylval.ival = atol((char*)yytext);
  308 
  309     if (errno == 0) {
  310     status  = INT;
  311     } else {
  312         ut_handle_error_message("Invalid integer\n", stderr);
  313 
  314     status  = ERR;
  315     }
  316 
  317     BEGIN INITIAL;
  318     return status;
  319 }
  320 
  321 (log|lg){space}*{logref} {
  322     yylval.rval = 10;
  323     return LOGREF;
  324 }
  325 
  326 ln{space}*{logref} {
  327     yylval.rval = M_E;
  328     return LOGREF;
  329 }
  330 
  331 lb{space}*{logref} {
  332     yylval.rval = 2;
  333     return LOGREF;
  334 }
  335 
  336 <INITIAL,CLOCK_SEEN>{id} {
  337     yylval.id = strdup((char*)yytext);
  338 
  339     BEGIN ID_SEEN;
  340     return ID;
  341 }
  342 
  343 . {
  344     BEGIN INITIAL;
  345     return yytext[0];
  346 }
  347 
  348 %%