LTP GCOV extension - code coverage report
Current view: directory - and-httpd/src - conf.c
Test: And-httpd coverage
Date: 2006-09-11 Instrumented lines: 455
Code covered: 79.8 % Executed lines: 363

       1                 : /*
       2                 :  *  Copyright (C) 2005  James Antill
       3                 :  *
       4                 :  *  This library is free software; you can redistribute it and/or
       5                 :  *  modify it under the terms of the GNU Lesser General Public
       6                 :  *  License as published by the Free Software Foundation; either
       7                 :  *  version 2 of the License, or (at your option) any later version.
       8                 :  *
       9                 :  *  This library is distributed in the hope that it will be useful,
      10                 :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11                 :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12                 :  *  Lesser General Public License for more details.
      13                 :  *
      14                 :  *  You should have received a copy of the GNU Lesser General Public
      15                 :  *  License along with this library; if not, write to the Free Software
      16                 :  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17                 :  *
      18                 :  *  email: james@and.org
      19                 :  */
      20                 : /* configuration file functions */
      21                 : 
      22                 : #define EX_UTILS_NO_FUNCS 1
      23                 : #include "ex_utils.h"
      24                 : 
      25                 : #include "conf.h"
      26                 : 
      27                 : #include <limits.h>
      28                 : 
      29                 : #include "mk.h"
      30                 : 
      31                 : #define CLEN COMPILE_STRLEN
      32                 : 
      33                 : #define VPREFIX(vstr, p, l, cstr)                                       \
      34                 :     (((l) >= CLEN(cstr)) &&                                             \
      35                 :      vstr_cmp_buf_eq(vstr, p, CLEN(cstr), cstr, CLEN(cstr)))
      36                 : 
      37                 : Conf_parse *conf_parse_make(Vstr_conf *conf)
      38           38913 : {
      39           38913 :   Conf_parse *ret   = MK(sizeof(Conf_parse));
      40           38913 :   Vstr_sects *sects = vstr_sects_make(4);
      41           38913 :   Vstr_base *s1     = vstr_make_base(conf);
      42           38913 :   Vstr_base *s2     = vstr_make_base(conf);
      43           38913 :   unsigned int *ptr = MK(sizeof(unsigned int) * 4);
      44                 : 
      45           38913 :   if (!ret || !s1 || !sects || !ptr)
      46                 :   {
      47               0 :     F(ret);
      48               0 :     vstr_sects_free(sects);
      49               0 :     vstr_free_base(s1);
      50               0 :     vstr_free_base(s2);
      51               0 :     F(ptr);
      52               0 :     return (NULL);
      53                 :   }
      54                 : 
      55           38913 :   ret->sects     = sects;
      56           38913 :   ret->data      = s1;
      57           38913 :   ret->tmp       = s2;
      58           38913 :   ret->types_sz  = 4;
      59           38913 :   ret->types_ptr = ptr;
      60           38913 :   ret->uvals_sz  = 0;
      61           38913 :   ret->uvals_num = 0;
      62           38913 :   ret->uvals_ptr = NULL;
      63           38913 :   ret->state     = CONF_PARSE_STATE_BEG;
      64           38913 :   ret->depth     = 0;
      65                 :   
      66           38913 :   return (ret);
      67                 : }
      68                 : 
      69                 : void conf_parse_free(Conf_parse *conf)
      70           38917 : {
      71           38917 :   if (!conf)
      72               0 :     return;
      73                 :   
      74           38917 :   F(conf->types_ptr);
      75           38917 :   vstr_sects_free(conf->sects);
      76           38917 :   vstr_free_base(conf->data);
      77           38917 :   vstr_free_base(conf->tmp);
      78                 : 
      79           82244 :   while (conf->uvals_num)
      80            4410 :     vstr_ref_del(conf->uvals_ptr[--conf->uvals_num].ref);
      81           38917 :   F(conf->uvals_ptr);
      82                 :   
      83           38917 :   F(conf);  
      84                 : }
      85                 : 
      86                 : static int conf__parse_type_add(Conf_parse *conf, unsigned int type)
      87          205064 : {
      88          205064 :   unsigned int *ptr = NULL;
      89                 : 
      90          102532 :   ASSERT(conf->types_sz <= conf->sects->sz);
      91                 :   
      92          205064 :   if (conf->types_sz == conf->sects->sz)
      93          188054 :     goto fin_ok;
      94                 : 
      95           17010 :   if (!MV(conf->types_ptr, ptr, sizeof(unsigned int) * conf->sects->sz))
      96               0 :     return (FALSE);
      97           17010 :   conf->types_sz  = conf->sects->sz;
      98                 :   
      99          205064 :  fin_ok:
     100          205064 :   conf->types_ptr[conf->sects->num - 1] = type;
     101                 :   
     102          205064 :   return (TRUE);
     103                 : }
     104                 : 
     105                 : 
     106                 : static size_t conf__parse_ws(Conf_parse *conf, size_t pos, size_t len)
     107          156576 : {
     108          156576 :   conf->state = CONF_PARSE_STATE_CHOOSE;
     109          156576 :   return (vstr_spn_cstr_chrs_fwd(conf->data, pos, len, " \t\v\r\n"));
     110                 : }
     111                 : 
     112                 : /* if the last token is a line comment token ... comment out that line */
     113                 : static size_t conf__parse_comment(Conf_parse *conf, size_t pos, size_t len)
     114          153090 : {
     115          153090 :   Vstr_sect_node *node = NULL;
     116                 : 
     117           76545 :   ASSERT(conf->sects);
     118                 :   
     119          153090 :   if (conf->sects->malloc_bad)
     120               0 :     return (0);
     121                 : 
     122           76545 :   ASSERT(conf->sects->num);
     123                 :   
     124          153090 :   node = VSTR_SECTS_NUM(conf->sects, conf->sects->num);
     125                 :               
     126          153090 :   if (node->len >= 1)
     127                 :   {
     128          153090 :     Vstr_base *data = conf->data;
     129          153090 :     int byte = vstr_export_chr(data, node->pos);
     130          153090 :     size_t p = node->pos;
     131          153090 :     size_t l = node->len;
     132                 :     
     133          153090 :     if (((byte == ';') && (vstr_spn_cstr_chrs_fwd(data, p, l, ";") == l)) ||
     134                 :         ((byte == '#') && (vstr_spn_cstr_chrs_fwd(data, p, l, "#") == l)))
     135                 :     {
     136            8696 :       vstr_sects_del(conf->sects, conf->sects->num);
     137            8696 :       conf->state = CONF_PARSE_STATE_CHOOSE;
     138            8696 :       return (vstr_cspn_cstr_chrs_fwd(conf->data, pos, len, "\n"));
     139                 :     }
     140                 :   }
     141                 :   
     142          144394 :   return (0);
     143                 : }
     144                 : 
     145                 : static int conf__parse_beg_list(Conf_parse *conf, size_t pos,
     146                 :                                 unsigned int *list_nums)
     147           47302 : {
     148           47302 :   if (conf->depth >= CONF_PARSE_LIST_DEPTH_SZ)
     149               0 :     return (FALSE);
     150                 :   
     151           47302 :   vstr_sects_add(conf->sects, pos, 0);
     152           47302 :   conf__parse_type_add(conf, CONF_TOKEN_TYPE_ERR);
     153           47302 :   list_nums[conf->depth++] = conf->sects->num;
     154                 :   
     155           47302 :   conf->state = CONF_PARSE_STATE_CHOOSE;
     156           47302 :   return (TRUE);
     157                 : }
     158                 : 
     159                 : static int conf__parse_end_list(Conf_parse *conf, unsigned int *list_nums,
     160                 :                                 int byte)
     161           47302 : {
     162           47302 :   Vstr_sects *sects = conf->sects;
     163           47302 :   unsigned int depth_beg_num = 0;
     164           47302 :   Vstr_sect_node *node = NULL;
     165                 :   
     166           47302 :   if (!conf->depth)
     167               0 :     return (FALSE);
     168                 : 
     169           47302 :   depth_beg_num = list_nums[--conf->depth];
     170           47302 :   node = VSTR_SECTS_NUM(sects, depth_beg_num);
     171           47302 :   if (byte == ']')
     172                 :   {
     173            5720 :     conf->types_ptr[depth_beg_num - 1] = CONF_TOKEN_TYPE_SLIST;
     174            5720 :     if (vstr_export_chr(conf->data, node->pos) != '[')
     175               0 :       return (FALSE);
     176                 :   }
     177                 :   
     178           47302 :   if (byte == ')')
     179                 :   {
     180           41582 :     conf->types_ptr[depth_beg_num - 1] = CONF_TOKEN_TYPE_CLIST;
     181           41582 :     if (vstr_export_chr(conf->data, node->pos) != '(')
     182               0 :       return (FALSE);
     183                 :   }
     184                 :   
     185           23651 :   ASSERT(!node->len);
     186           47302 :   node->len = sects->num - depth_beg_num;
     187                 :   
     188           47302 :   conf->state = CONF_PARSE_STATE_CHOOSE;
     189           47302 :   return (TRUE);
     190                 : }
     191                 : 
     192                 : static void conf__parse_beg_quote_d(Conf_parse *conf, size_t pos,
     193                 :                                     unsigned int *list_nums)
     194            2824 : {
     195            1412 :   ASSERT(conf->depth <= CONF_PARSE_LIST_DEPTH_SZ);
     196                 :             
     197            2824 :   vstr_sects_add(conf->sects, pos, 0);
     198            2824 :   conf__parse_type_add(conf, CONF_TOKEN_TYPE_QUOTE_D);
     199            2824 :   list_nums[conf->depth++] = conf->sects->num;
     200                 :   
     201            2824 :   conf->state = CONF_PARSE_STATE_QUOTE_D_BEG;
     202            2824 : }
     203                 : 
     204                 : static void conf__parse_beg_quote_s(Conf_parse *conf, size_t pos,
     205                 :                                     unsigned int *list_nums)
     206            1848 : {
     207             924 :   ASSERT(conf->depth <= CONF_PARSE_LIST_DEPTH_SZ);
     208                 :             
     209            1848 :   vstr_sects_add(conf->sects, pos, 0);
     210            1848 :   conf__parse_type_add(conf, CONF_TOKEN_TYPE_QUOTE_S);
     211            1848 :   list_nums[conf->depth++] = conf->sects->num;
     212                 :   
     213            1848 :   conf->state = CONF_PARSE_STATE_QUOTE_S_BEG;
     214            1848 : }
     215                 : 
     216                 : static void conf__parse_beg_quote_xxx(Conf_parse *conf, unsigned int *list_nums,
     217                 :                                       int three)
     218            4672 : {
     219            4672 :   Vstr_sects *sects = conf->sects;
     220            4672 :   unsigned int depth_beg_num = 0;
     221            4672 :   size_t mv_pos = 1;
     222            4672 :   unsigned int state = 0;
     223                 :   
     224            2336 :   ASSERT(conf->depth);
     225                 :   
     226            4672 :   depth_beg_num = list_nums[conf->depth - 1];
     227                 : 
     228            4672 :   if (conf->state == CONF_PARSE_STATE_QUOTE_S_BEG)
     229            1848 :     state = CONF_PARSE_STATE_QUOTE_S_END;
     230            4672 :   if (conf->state == CONF_PARSE_STATE_QUOTE_D_BEG)
     231            2824 :     state = CONF_PARSE_STATE_QUOTE_D_END;
     232                 : 
     233            4672 :   if (three)
     234                 :   {
     235              52 :     mv_pos = 3;
     236              52 :     state += CONF_PARSE_STATE_QUOTE_X2XXX;
     237              52 :     conf->types_ptr[depth_beg_num - 1] += 2;
     238                 :   }
     239                 :   
     240            4672 :   VSTR_SECTS_NUM(sects, depth_beg_num)->pos += mv_pos;
     241                 :   
     242            4672 :   conf->state = state;
     243            4672 : }
     244                 : 
     245                 : static size_t conf__parse_beg_unquote(Conf_parse *conf, size_t pos, size_t len,
     246                 :                                       unsigned int *list_nums)
     247              88 : {
     248              88 :   size_t plen = 1;
     249              88 :   int d   = FALSE;
     250              88 :   int xxx = FALSE;
     251                 :   
     252                 :   if (FALSE) { }
     253             104 :   else if (VPREFIX(conf->data, pos, len, "\"\"\""))
     254                 :   {
     255              16 :     d   = TRUE;
     256              16 :     xxx = TRUE;
     257                 :   }
     258             100 :   else if (VPREFIX(conf->data, pos, len, "\""))
     259                 :   {
     260              28 :     d   = TRUE;
     261              28 :     xxx = FALSE;
     262                 :   }
     263              64 :   else if (VPREFIX(conf->data, pos, len, "'''"))
     264                 :   {
     265              20 :     d   = FALSE;
     266              20 :     xxx = TRUE;
     267                 :   }
     268              48 :   else if (VPREFIX(conf->data, pos, len, "'"))
     269                 :   {
     270              24 :     d   = FALSE;
     271              24 :     xxx = FALSE;
     272                 :   }
     273                 :   else
     274               0 :     return (0);
     275                 : 
     276              88 :   if (d)
     277              44 :     conf__parse_beg_quote_d(conf, pos, list_nums);
     278                 :   else
     279              44 :     conf__parse_beg_quote_s(conf, pos, list_nums);
     280                 : 
     281              88 :   if (!xxx)
     282              52 :     conf__parse_beg_quote_xxx(conf, list_nums, FALSE);
     283                 :   else
     284                 :   {
     285              36 :     plen = 3;
     286              36 :     conf__parse_beg_quote_xxx(conf, list_nums, TRUE);
     287                 :   }
     288                 : 
     289              88 :   conf->state += CONF_PARSE_STATE_QUOTE2UNQUOTE_END;
     290                 :   
     291              88 :   len -= plen; pos += plen;
     292              88 :   if (VPREFIX(conf->data, pos, len, "\\\n")) /* allow first line */
     293                 :   {
     294               4 :     unsigned int depth_beg_num = list_nums[conf->depth - 1];
     295                 : 
     296               4 :     VSTR_SECTS_NUM(conf->sects, depth_beg_num)->pos += CLEN("\\\n");
     297               4 :     plen                                            += CLEN("\\\n");
     298                 :   }
     299                 :   
     300              88 :   return (plen);
     301                 : }
     302                 : 
     303                 : static void conf__parse_end_quote_xxx(Conf_parse *conf, size_t pos,
     304                 :                                       unsigned int *list_nums)
     305            4672 : {
     306            4672 :   Vstr_sects *sects = conf->sects;
     307            4672 :   unsigned int depth_beg_num = 0;
     308            4672 :   size_t beg_pos = 0;
     309                 :   
     310            2336 :   ASSERT(conf->depth);
     311                 : 
     312            4672 :   depth_beg_num = list_nums[--conf->depth];
     313            4672 :   beg_pos = VSTR_SECTS_NUM(sects, depth_beg_num)->pos;
     314            4672 :   VSTR_SECTS_NUM(sects, depth_beg_num)->pos = beg_pos;
     315            4672 :   VSTR_SECTS_NUM(sects, depth_beg_num)->len = pos - beg_pos;
     316                 :   
     317            4672 :   conf->state = CONF_PARSE_STATE_LIST_END_OR_WS;
     318            4672 : }
     319                 : 
     320                 : static int conf__parse_esc_quote(Conf_parse *conf, unsigned int *list_nums,
     321                 :                                  size_t pos, size_t len, unsigned int type)
     322           18444 : {
     323           18444 :   Vstr_sects *sects = conf->sects;
     324           18444 :   unsigned int depth_beg_num = 0;
     325                 : 
     326            9222 :   ASSERT(conf->depth);
     327                 : 
     328           18444 :   if (len < 2)
     329               0 :     return (FALSE);
     330                 :   
     331           18444 :   depth_beg_num = list_nums[conf->depth - 1];
     332           18444 :   if ((pos == VSTR_SECTS_NUM(sects, depth_beg_num)->pos) &&
     333                 :       vstr_cmp_cstr_eq(conf->data, pos, CLEN("\\\n"), "\\\n"))
     334                 :   {
     335               8 :     VSTR_SECTS_NUM(sects, depth_beg_num)->pos += CLEN("\\\n");
     336               8 :     return (TRUE);
     337                 :   }
     338                 :   
     339           18436 :   if (conf->types_ptr[depth_beg_num - 1] == type)
     340            1156 :     conf->types_ptr[depth_beg_num - 1] += CONF_TOKEN_TYPE_2ESC;
     341                 : 
     342           18436 :   return (TRUE);
     343                 : }
     344                 : #define CONF__SC_PARSE_ESC_QUOTE(x) do {                                \
     345                 :       ASSERT(vstr_export_chr(data, pos) == '\\');                       \
     346                 :                                                                         \
     347                 :       if (!conf__parse_esc_quote(conf, list_nums, pos, len, x))         \
     348                 :         return (CONF_PARSE_ERR);                                        \
     349                 :       plen = 2;                                                         \
     350                 :     } while (FALSE)
     351                 : 
     352                 : #define CONF__SC_PARSE_QUOTE_X_BEG(x) do {                           \
     353                 :       if (!VPREFIX(data, pos, len, x))                               \
     354                 :         conf__parse_beg_quote_xxx(conf, list_nums, FALSE);           \
     355                 :       else                                                           \
     356                 :       {                                                              \
     357                 :         plen = 2;                                                    \
     358                 :         conf__parse_beg_quote_xxx(conf, list_nums, TRUE);            \
     359                 :       }                                                              \
     360                 :     } while (FALSE)
     361                 : 
     362                 : #define CONF__SC_PARSE_QUOTE_XXX_END(x, y, z) do {                      \
     363                 :       if (!(plen = vstr_cspn_cstr_chrs_fwd(data, pos, len, x)))         \
     364                 :       {                                                                 \
     365                 :         plen = 3;                                                       \
     366                 :         if (VPREFIX(data, pos, len, y))                                 \
     367                 :           conf__parse_end_quote_xxx(conf, pos, list_nums);              \
     368                 :         else if (vstr_export_chr(data, pos) != '\\')                    \
     369                 :           plen = 1;                                                     \
     370                 :         else /* \x */                                                   \
     371                 :           CONF__SC_PARSE_ESC_QUOTE(CONF_TOKEN_TYPE_QUOTE_ ## z);        \
     372                 :       }                                                                 \
     373                 :     } while (FALSE)
     374                 : 
     375                 : #define CONF__SC_PARSE_QUOTE_X_END(x, y, z) do {                        \
     376                 :       if (!(plen = vstr_cspn_cstr_chrs_fwd(data, pos, len, x)))         \
     377                 :       {                                                                 \
     378                 :         plen = 1;                                                       \
     379                 :         if (vstr_export_chr(data, pos) == y)                            \
     380                 :           conf__parse_end_quote_xxx(conf, pos, list_nums);              \
     381                 :         else /* \x */                                                   \
     382                 :           CONF__SC_PARSE_ESC_QUOTE(CONF_TOKEN_TYPE_QUOTE_ ## z);        \
     383                 :       }                                                                 \
     384                 :     } while (FALSE)
     385                 : 
     386                 : #define CONF__SC_PARSE_UNQUOTE_END(x) do {                           \
     387                 :       if (!(plen = vstr_srch_cstr_buf_fwd(data, pos, len, x)))       \
     388                 :         plen = len;                                                  \
     389                 :       else                                                           \
     390                 :       {                                                              \
     391                 :         conf__parse_end_quote_xxx(conf, plen, list_nums);            \
     392                 :         plen -= pos;                                                 \
     393                 :         plen += CLEN(x);                                             \
     394                 :       }                                                              \
     395                 :     } while (FALSE)
     396                 : 
     397                 : int conf_parse_lex(Conf_parse *conf, size_t pos, size_t len)
     398            5146 : {
     399                 :   unsigned int list_nums[CONF_PARSE_LIST_DEPTH_SZ + 1];
     400            5146 :   Vstr_base *data = NULL;
     401                 : 
     402            2573 :   ASSERT(conf && conf->data && conf->sects &&
     403                 :          conf->types_ptr && conf->types_sz);
     404                 :   
     405            5146 :   data = conf->data;
     406                 : 
     407            5146 :   if (conf->state != CONF_PARSE_STATE_BEG)
     408               0 :     return (CONF_PARSE_ERR);
     409                 : 
     410          479671 :   while (len)
     411                 :   {
     412          471952 :     size_t plen = 0; /* amount parsed this loop */
     413                 :     
     414          471952 :     switch (conf->state)
     415                 :     {
     416                 :       case CONF_PARSE_STATE_BEG: /* unix she-bang */
     417            5146 :         conf->state = CONF_PARSE_STATE_CHOOSE;
     418            5146 :         if (VPREFIX(data, pos, len, "#!"))
     419                 :         {
     420               4 :           plen = vstr_cspn_cstr_chrs_fwd(data, pos, len, "\n");
     421               4 :           conf->state = CONF_PARSE_STATE_WS;
     422                 :         }
     423            2573 :         break;
     424                 :         
     425                 :       case CONF_PARSE_STATE_WS:
     426               4 :         if (!(plen = conf__parse_ws(conf, pos, len)))
     427               0 :           return (CONF_PARSE_ERR);
     428               2 :         break;
     429                 :         
     430                 :       case CONF_PARSE_STATE_LIST_END_OR_WS:
     431                 :       {
     432            4672 :         int byte = vstr_export_chr(data, pos);
     433                 : 
     434            4672 :         plen = 1;
     435            4672 :         switch (byte)
     436                 :         {
     437                 :           case ' ':  /* whitespace */
     438                 :           case '\t': /* whitespace */
     439                 :           case '\v': /* whitespace */
     440                 :           case '\r': /* whitespace */
     441                 :           case '\n': /* whitespace */
     442            4044 :             plen = conf__parse_ws(conf, pos, len);
     443            4044 :             break;
     444                 :             
     445                 :           case ')':
     446                 :           case ']':
     447             628 :             if (!conf__parse_end_list(conf, list_nums, byte))
     448               0 :               return (CONF_PARSE_ERR);
     449             314 :             break;
     450                 :           default:
     451               0 :             return (CONF_PARSE_ERR);
     452                 :         }
     453                 :       }
     454            2336 :       break;
     455                 :         
     456                 :       case CONF_PARSE_STATE_CHOOSE:
     457                 :       {
     458          259624 :         int byte = vstr_export_chr(data, pos);
     459                 : 
     460          259624 :         plen = 1;
     461          259624 :         switch (byte)
     462                 :         {
     463                 :           case ' ':  /* whitespace */
     464                 :           case '\t': /* whitespace */
     465                 :           case '\v': /* whitespace */
     466                 :           case '\r': /* whitespace */
     467                 :           case '\n': /* whitespace */
     468           43740 :             plen = conf__parse_ws(conf, pos, len);
     469           43740 :             break;
     470                 :             
     471                 :           case ')':
     472                 :           case ']':
     473           10828 :             if (!conf__parse_end_list(conf, list_nums, byte))
     474               0 :               return (CONF_PARSE_ERR);
     475            5414 :             break;
     476                 : 
     477                 :           case '(':
     478                 :           case '[':
     479           47294 :             if (!conf__parse_beg_list(conf, pos, list_nums))
     480               0 :               return (CONF_PARSE_ERR);
     481           23647 :             break;
     482                 : 
     483                 :           case '"':
     484            2780 :             conf__parse_beg_quote_d(conf, pos, list_nums);
     485            2780 :             break;
     486                 :           case '\'':
     487            1804 :             conf__parse_beg_quote_s(conf, pos, list_nums);
     488            1804 :             break;
     489                 :             
     490                 :           case '@': /* allow "raw" strings, for backslashes, @ == C# */
     491                 :           case 'r': /* allow "raw" strings, for backslashes, r == python */
     492            2516 :             if (len > 1)
     493                 :             {
     494            2516 :               char tmp = vstr_export_chr(data, pos + 1);
     495            2516 :               if ((tmp == '"') || (tmp == '\''))
     496                 :               {
     497              88 :                 conf->state = CONF_PARSE_STATE_UNQUOTE_BEG;
     498              88 :                 break;
     499                 :               }
     500                 :             }
     501                 :             
     502                 :           default:
     503          153090 :             plen = vstr_cspn_cstr_chrs_fwd(data, pos, len, " \t\v\r\n\"'()[]");
     504          153090 :             conf->state = CONF_PARSE_STATE_SYMBOL_END;
     505          153090 :             vstr_sects_add(conf->sects, pos, plen);
     506          153090 :             conf__parse_type_add(conf, CONF_TOKEN_TYPE_SYMBOL);
     507                 :             break;            
     508                 :         }
     509                 :       }
     510          129812 :       break;
     511                 :         
     512                 :       case CONF_PARSE_STATE_QUOTE_D_BEG:
     513            2780 :         CONF__SC_PARSE_QUOTE_X_BEG("\"\"");
     514            1390 :         break;
     515                 :         
     516                 :       case CONF_PARSE_STATE_QUOTE_S_BEG:
     517            1804 :         CONF__SC_PARSE_QUOTE_X_BEG("''");
     518             902 :       break;
     519                 :         
     520                 :       case CONF_PARSE_STATE_UNQUOTE_BEG:
     521              88 :         if (!(plen = conf__parse_beg_unquote(conf, pos, len, list_nums)))
     522               0 :           return (CONF_PARSE_ERR);
     523              44 :         break;
     524                 :         
     525                 :       case CONF_PARSE_STATE_QUOTE_D_END:
     526           41240 :         CONF__SC_PARSE_QUOTE_X_END("\"\\", '"', D);
     527           20620 :         break;
     528                 :         
     529                 :       case CONF_PARSE_STATE_QUOTE_DDD_END:
     530              48 :         CONF__SC_PARSE_QUOTE_XXX_END("\"\\", "\"\"\"", DDD);
     531              24 :         break;
     532                 :         
     533                 :       case CONF_PARSE_STATE_QUOTE_S_END:
     534            3368 :         CONF__SC_PARSE_QUOTE_X_END("'\\", '\'', S);
     535            1684 :         break;
     536                 :         
     537                 :       case CONF_PARSE_STATE_QUOTE_SSS_END:
     538               0 :         CONF__SC_PARSE_QUOTE_XXX_END("'\\", "'''", SSS);
     539               0 :         break;
     540                 :         
     541                 :       case CONF_PARSE_STATE_UNQUOTE_DDD_END:
     542              16 :         CONF__SC_PARSE_UNQUOTE_END("\"\"\"");
     543               8 :         break;
     544                 :         
     545                 :       case CONF_PARSE_STATE_UNQUOTE_D_END:
     546              28 :         CONF__SC_PARSE_UNQUOTE_END("\"");
     547              14 :         break;
     548                 :         
     549                 :       case CONF_PARSE_STATE_UNQUOTE_SSS_END:
     550              20 :         CONF__SC_PARSE_UNQUOTE_END("'''");
     551              10 :         break;
     552                 :         
     553                 :       case CONF_PARSE_STATE_UNQUOTE_S_END:
     554              24 :         CONF__SC_PARSE_UNQUOTE_END("'");
     555              12 :         break;
     556                 :         
     557                 :       case CONF_PARSE_STATE_SYMBOL_END:
     558                 :       {
     559          153090 :         int byte = vstr_export_chr(data, pos);
     560                 : 
     561          153090 :         switch (byte)
     562                 :         {
     563                 :           case ' ':  /* whitespace */
     564                 :           case '\t': /* whitespace */
     565                 :           case '\v': /* whitespace */
     566                 :           case '\r': /* whitespace */
     567                 :           case '\n': /* whitespace */
     568          117236 :             if (!(plen = conf__parse_comment(conf, pos, len)))
     569          108788 :               plen = conf__parse_ws(conf, pos, len);
     570           58618 :             break;
     571                 :             
     572                 :           case ')':
     573                 :           case ']':
     574           35846 :             if (!(plen = conf__parse_comment(conf, pos, len)))
     575                 :             {
     576           35846 :               plen = 1;
     577           35846 :               if (!conf__parse_end_list(conf, list_nums, byte))
     578               0 :                 return (CONF_PARSE_ERR);
     579                 :             }
     580           17923 :             break;
     581                 : 
     582                 :           case '(':
     583                 :           case '[':
     584               8 :             if (!(plen = conf__parse_comment(conf, pos, len)))
     585                 :             {
     586               8 :               plen = 1;
     587               8 :               if (!conf__parse_beg_list(conf, pos, list_nums))
     588               0 :                 return (CONF_PARSE_ERR);
     589                 :             }
     590               4 :             break;
     591                 :             
     592                 :           case '"':
     593                 :           case '\'':
     594               0 :             return (CONF_PARSE_ERR);
     595                 :           default:
     596               0 :             assert(FALSE);
     597               0 :             return (CONF_PARSE_ERR);
     598                 :         }
     599                 :       }
     600           76545 :       break;
     601                 :       
     602                 :       default:
     603               0 :         assert(FALSE);
     604               0 :         return (CONF_PARSE_ERR);
     605                 :     }
     606                 : 
     607          471952 :     len -= plen; pos += plen;
     608                 :   }
     609                 : 
     610            5146 :   if (conf->sects->malloc_bad || conf->depth)
     611               0 :     return (CONF_PARSE_ERR);
     612                 : 
     613            5146 :   conf->state = CONF_PARSE_STATE_END;
     614            5146 :   return (CONF_PARSE_FIN);
     615                 : }
     616                 : #undef CONF__SC_PARSE_ESC_QUOTE
     617                 : #undef CONF__SC_PARSE_QUOTE_X_BEG
     618                 : #undef CONF__SC_PARSE_QUOTE_XXX_END
     619                 : #undef CONF__SC_PARSE_QUOTE_X_END
     620                 : #undef CONF__SC_PARSE_UNQUOTE_END
     621                 : 
     622                 : Conf_token *conf_token_make(void)
     623               0 : {
     624               0 :   Conf_token dummy = CONF_TOKEN_INIT;
     625               0 :   Conf_token *ret = MK(sizeof(Conf_token));
     626                 : 
     627               0 :   if (!ret)
     628               0 :     return (NULL);
     629                 :   
     630               0 :   *ret = dummy;
     631                 : 
     632               0 :   return (ret);
     633                 : }
     634                 : 
     635                 : void conf_token_free(Conf_token *token)
     636               0 : {
     637               0 :   F(token);
     638               0 : }
     639                 : 
     640                 : static const char *conf__token_name_map[] = {
     641                 :  "<** Error **>",
     642                 :  "Circular bracket list",
     643                 :  "Square bracket list",
     644                 :  "Quoted string (double, RAW)",
     645                 :  "Quoted string (double, with Escaping)",
     646                 :  "Quoted string (3x double, RAW)",
     647                 :  "Quoted string (3x double, with Escaping)",
     648                 :  "Quoted string (single, RAW)",
     649                 :  "Quoted string (single, with Escaping)",
     650                 :  "Quoted string (3x single, RAW)",
     651                 :  "Quoted string (3x single, with Escaping)",
     652                 :  "Symbol"
     653                 : };
     654                 : 
     655                 : const char *conf_token_name(const Conf_token *token)
     656           10436 : {
     657            5218 :   ASSERT(token);
     658                 : 
     659           10436 :   if (token->type > CONF_TOKEN_TYPE_SYMBOL)
     660               0 :     return ("User type");
     661                 :   
     662           10436 :   return (conf__token_name_map[token->type]);
     663                 : }
     664                 : 
     665                 : int conf_sc_token_parse_uint(const Conf_parse *conf, Conf_token *token,
     666                 :                              unsigned int *val)
     667            4144 : {
     668            4144 :   unsigned int num = conf_token_list_num(token, token->depth_num);
     669            4144 :   int ern = CONF_SC_TYPE_RET_OK;
     670            4144 :   const Vstr_sect_node *pv = NULL;
     671            4144 :   unsigned int nflags = VSTR_FLAG02(PARSE_NUM, OVERFLOW, SEP);
     672            4144 :   size_t len = 0;
     673                 :   
     674            2072 :   ASSERT(val);
     675                 : 
     676            4144 :   if (!num)
     677               0 :     return (CONF_SC_TYPE_RET_ERR_NOT_EXIST);
     678            4144 :   conf_parse_token(conf, token);
     679            4144 :   if (!(pv = conf_token_value(token)))
     680               0 :     return (CONF_SC_TYPE_RET_ERR_PARSE);
     681                 : 
     682            4144 :   *val = vstr_parse_uint(conf->data, pv->pos, pv->len, nflags, &len, NULL);
     683            4144 :   if (len != pv->len)
     684               0 :     ern = CONF_SC_TYPE_RET_ERR_PARSE;
     685                 :   
     686            4144 :   return (ern);
     687                 : }
     688                 : 
     689                 : int conf_sc_token_parse_ulong(const Conf_parse *conf, Conf_token *token,
     690                 :                               unsigned long *val)
     691               0 : {
     692               0 :   unsigned int num = conf_token_list_num(token, token->depth_num);
     693               0 :   int ern = CONF_SC_TYPE_RET_OK;
     694               0 :   const Vstr_sect_node *pv = NULL;
     695               0 :   unsigned int nflags = VSTR_FLAG02(PARSE_NUM, OVERFLOW, SEP);
     696               0 :   size_t len = 0;
     697                 :   
     698               0 :   ASSERT(val);
     699                 : 
     700               0 :   if (!num)
     701               0 :     return (CONF_SC_TYPE_RET_ERR_NOT_EXIST);
     702               0 :   conf_parse_token(conf, token);
     703               0 :   if (!(pv = conf_token_value(token)))
     704               0 :     return (CONF_SC_TYPE_RET_ERR_PARSE);
     705                 : 
     706               0 :   *val = vstr_parse_ulong(conf->data, pv->pos, pv->len, nflags, &len, NULL);
     707               0 :   if (len != pv->len)
     708               0 :     ern = CONF_SC_TYPE_RET_ERR_PARSE;
     709                 :   
     710               0 :   return (ern);
     711                 : }
     712                 : 
     713                 : int conf_sc_token_parse_uintmax(const Conf_parse *conf, Conf_token *token,
     714                 :                                 uintmax_t *val)
     715           58512 : {
     716           58512 :   unsigned int num = conf_token_list_num(token, token->depth_num);
     717           58512 :   int ern = CONF_SC_TYPE_RET_OK;
     718           58512 :   const Vstr_sect_node *pv = NULL;
     719           58512 :   unsigned int nflags = VSTR_FLAG02(PARSE_NUM, OVERFLOW, SEP);
     720           58512 :   size_t len = 0;
     721                 :   
     722           29256 :   ASSERT(val);
     723                 : 
     724           58512 :   if (!num)
     725               0 :     return (CONF_SC_TYPE_RET_ERR_NOT_EXIST);
     726           58512 :   conf_parse_token(conf, token);
     727           58512 :   if (!(pv = conf_token_value(token)))
     728               0 :     return (CONF_SC_TYPE_RET_ERR_PARSE);
     729                 : 
     730           58512 :   *val = vstr_parse_uintmax(conf->data, pv->pos, pv->len, nflags, &len, NULL);
     731           58512 :   if (len != pv->len)
     732           13728 :     ern = CONF_SC_TYPE_RET_ERR_PARSE;
     733                 :   
     734           58512 :   return (ern);
     735                 : }
     736                 : 
     737                 : int conf_sc_token_app_vstr(const Conf_parse *conf, Conf_token *token,
     738                 :                            Vstr_base *s1,
     739                 :                            const Vstr_base **a_s1, size_t *a_pos, size_t *a_len)
     740           16512 : {
     741           16512 :   unsigned int num = conf_token_list_num(token, token->depth_num);
     742           16512 :   int ern = CONF_SC_TYPE_RET_OK;
     743           16512 :   const Vstr_sect_node *pv = NULL;
     744                 :   
     745            8256 :   ASSERT(s1);
     746                 : 
     747           16512 :   if (!num)
     748               0 :     return (CONF_SC_TYPE_RET_ERR_NOT_EXIST);
     749           16512 :   conf_parse_token(conf, token);
     750           16512 :   if (!(pv = conf_token_value(token)))
     751               0 :     return (CONF_SC_TYPE_RET_ERR_PARSE);
     752                 :   
     753           16512 :   if (vstr_add_vstr(s1, s1->len, conf->data, pv->pos, pv->len,
     754                 :                     VSTR_TYPE_SUB_BUF_REF))
     755                 :   {
     756           16512 :     *a_s1  = s1;
     757           16512 :     *a_pos = (s1->len - pv->len) + 1;
     758           16512 :     *a_len = pv->len;
     759                 :   }
     760                 :   
     761           16512 :   return (ern);
     762                 : }
     763                 : 
     764                 : int conf_sc_token_sub_vstr(const Conf_parse *conf, Conf_token *token,
     765                 :                            Vstr_base *s1, size_t pos, size_t len)
     766             144 : {
     767             144 :   unsigned int num = conf_token_list_num(token, token->depth_num);
     768             144 :   int ern = CONF_SC_TYPE_RET_OK;
     769             144 :   const Vstr_sect_node *pv = NULL;
     770                 :   
     771              72 :   ASSERT(s1);
     772                 :   
     773             144 :   if (!num)
     774               0 :     return (CONF_SC_TYPE_RET_ERR_NOT_EXIST);
     775             144 :   conf_parse_token(conf, token);
     776             144 :   if (!(pv = conf_token_value(token)))
     777               0 :     return (CONF_SC_TYPE_RET_ERR_PARSE);
     778                 : 
     779             144 :   vstr_sub_vstr(s1, pos, len, conf->data, pv->pos, pv->len,
     780                 :                 VSTR_TYPE_SUB_BUF_REF);
     781                 :   
     782             144 :   return (ern);
     783                 : }
     784                 : 
     785                 : #define SUB2(x, y, z) vstr_sub_cstr_buf(x, y, 2, z)
     786                 : int conf_sc_conv_unesc(Vstr_base *s1, size_t pos, size_t len,
     787                 :                        size_t *ret_len)
     788            1152 : {
     789                 :   size_t dummy_len;
     790                 : 
     791            1152 :   if (!ret_len) ret_len = &dummy_len;
     792                 :   
     793            1152 :   *ret_len = len;
     794                 :   
     795           20736 :   while (!s1->conf->malloc_bad && (len > 1))
     796                 :   {
     797           18432 :     size_t plen = vstr_cspn_cstr_chrs_fwd(s1, pos, len, "\\");
     798                 : 
     799           18432 :     if (!plen)
     800                 :     {
     801           18432 :       char chr = vstr_export_chr(s1, pos + 1);
     802                 : 
     803           18432 :       if (chr == '\n')
     804                 :       {
     805               0 :         vstr_del(s1, pos, 2);
     806               0 :         len -= 2; *ret_len -= 2;
     807               0 :         continue;
     808                 :       }
     809           18432 :       else if (chr == 't') { SUB2(s1, pos, "\t"); --len; --*ret_len; }
     810           18432 :       else if (chr == 'v') { SUB2(s1, pos, "\v"); --len; --*ret_len; }
     811           18432 :       else if (chr == 'r') { SUB2(s1, pos, "\r"); --len; --*ret_len; }
     812           18432 :       else if (chr == 'n') { SUB2(s1, pos, "\n"); --len; --*ret_len; }
     813           18432 :       else if (chr == 'b') { SUB2(s1, pos, "\b"); --len; --*ret_len; }
     814           18432 :       else if ((chr >= '0') && (chr <= '9'))
     815                 :       { /* \0 == NIL \377 | \0377 == UCHAR_MAX */
     816               0 :         unsigned char val = 0;
     817               0 :         unsigned int nflags =  8 | VSTR_FLAG_PARSE_NUM_OVERFLOW;
     818               0 :         unsigned int nlen = min_t(unsigned int, 4, len - 1);
     819                 :         
     820                 :         /* FIXME: ... parse uchar */
     821               0 :         val = vstr_parse_ushort(s1, pos + 1, nlen, nflags, &plen, NULL);
     822               0 :         vstr_sub_rep_chr(s1, pos, plen + 1, val, 1);
     823               0 :         len      -= plen; /* byte == \ ... so not plen + 1 */
     824               0 :         *ret_len -= plen;
     825                 :       }
     826           27648 :       else if ((chr == 'x') && (len >= 4))
     827                 :       { /* \x00 == NIL \xff == UCHAR_MAX */
     828           18432 :         unsigned char val = 0;
     829           18432 :         unsigned int nflags = 16 | VSTR_FLAG_PARSE_NUM_OVERFLOW;
     830                 :         
     831           18432 :         val = vstr_parse_ushort(s1, pos + 2, 2, nflags, NULL, NULL);
     832           18432 :         vstr_sub_rep_chr(s1, pos, 4, val, 1);
     833           18432 :         len      -= 3; /* byte == \ ... so not 4 */
     834           18432 :         *ret_len -= 3;
     835                 :       }
     836                 :       else
     837                 :       { /* rm \ ... Eg. \" == " and \\ == \ */
     838               0 :         vstr_del(s1, pos, 1);
     839               0 :         --len; --*ret_len;
     840                 :       }
     841           18432 :       plen = 1;
     842                 :     }
     843                 :     
     844           18432 :     len -= plen;
     845           18432 :     pos += plen;
     846                 :   }
     847                 : 
     848            1152 :   return (!s1->conf->malloc_bad);
     849                 : }
     850                 : #undef SUB
     851                 : 
     852                 : int conf_token_set_user_value(Conf_parse *conf, Conf_token *token,
     853                 :                               unsigned int type,
     854                 :                               Vstr_ref *uval, unsigned int nxt)
     855            5398 : {
     856            5398 :   Vstr_ref *oref = NULL;
     857                 :   
     858            2699 :   ASSERT(conf && token);
     859            2699 :   ASSERT(type <= (UINT_MAX - CONF_TOKEN_TYPE_USER_BEG));
     860                 :   
     861                 :   /* must not be a CLIST or SLIST */
     862            5398 :   if ((token->type == CONF_TOKEN_TYPE_CLIST) ||
     863                 :       (token->type == CONF_TOKEN_TYPE_SLIST))
     864               0 :     return (FALSE);
     865                 : 
     866            5398 :   if (token->type >= CONF_TOKEN_TYPE_USER_BEG)
     867             990 :     oref = conf->uvals_ptr[token->u.uval_num].ref;
     868                 :   else
     869                 :   {
     870            4408 :     if (conf->uvals_sz <= conf->uvals_num)
     871                 :     {
     872            3576 :       unsigned int num = (conf->uvals_sz << 1) + 1;
     873            3576 :       Conf__uval_store *uvals  = NULL;
     874                 : 
     875            3576 :       if (num <= conf->uvals_sz)
     876               0 :         return (FALSE);
     877                 :       
     878            3576 :       if (!conf->uvals_sz &&
     879                 :           !(conf->uvals_ptr = MK(sizeof(Conf__uval_store) * num)))
     880               0 :         return (FALSE);
     881            3576 :       else if (!MV(conf->uvals_ptr, uvals, sizeof(Conf__uval_store) * num))
     882               0 :         return (FALSE);
     883                 :       
     884            3576 :       conf->uvals_sz  = num; 
     885                 :     }
     886            4408 :     VSTR_SECTS_NUM(conf->sects, token->num)->pos = conf->uvals_num;
     887            4408 :     token->u.uval_num                            = conf->uvals_num;
     888                 :     
     889            4408 :     ++conf->uvals_num;
     890                 :   }
     891                 :   
     892            5398 :   token->type = CONF_TOKEN_TYPE_USER_BEG + type;
     893                 : 
     894            5398 :   conf->types_ptr[token->num - 1]        = token->type;
     895            5398 :   conf->uvals_ptr[token->u.uval_num].ref = NULL;
     896            5398 :   conf->uvals_ptr[token->u.uval_num].nxt = nxt;
     897            5398 :   if (uval)
     898            5050 :     conf->uvals_ptr[token->u.uval_num].ref = vstr_ref_add(uval);
     899                 :   
     900            5398 :   vstr_ref_del(oref);
     901                 :   
     902            5398 :   return (TRUE);
     903                 : }
     904                 : 
     905                 : void conf_parse_compress(Conf_parse *conf)
     906               0 : { /* FIXME: remove all Vstr data that isn't referenced, fixup sections */
     907                 :   (void)conf;
     908               0 : }
     909                 : 
     910                 : void conf_parse_backtrace(Vstr_base *out, const char *filename,
     911                 :                           const Conf_parse *conf, const Conf_token *token)
     912              72 : {
     913              72 :   const Vstr_sect_node *val = NULL;
     914                 : 
     915              72 :   if (!out)
     916               0 :     return;
     917                 :   
     918              72 :   if (conf->state != CONF_PARSE_STATE_END)
     919                 :   {
     920               0 :     vstr_add_fmt(out, out->len, "Syntax error in %s,  ", filename);
     921               0 :     vstr_add_fmt(out, out->len, "  State was: %d", conf->state);
     922               0 :     return;
     923                 :   }
     924                 : 
     925                 :   /* walk backwards */
     926              72 :   if (token->type > CONF_TOKEN_TYPE_SYMBOL)
     927               0 :     vstr_add_fmt(out, out->len, "Failed parse on node %u (%s %d)",
     928                 :                  token->num, conf_token_name(token),
     929                 :                  token->type - CONF_TOKEN_TYPE_SYMBOL);
     930              72 :   else if (!(val = conf_token_value(token)))
     931               0 :     vstr_add_fmt(out, out->len, "Failed parse on node %u [%s]",
     932                 :                  token->num, conf_token_name(token));
     933                 :   else
     934                 :   {
     935              72 :     Vstr_base *s1 = conf->data;
     936                 :     
     937              72 :     vstr_add_fmt(out, out->len, "Failed parse on node %u <%s> = ",
     938                 :                  token->num, conf_token_name(token));
     939              72 :     vstr_add_vstr(out, out->len, s1, val->pos, val->len, VSTR_TYPE_ADD_BUF_REF);
     940                 :   }
     941                 : }

Generated by: LTP GCOV extension version 1.4