Coverage Report

Created: 2025-11-09 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/scconf/sclex.c
Line
Count
Source
1
/*
2
 * $Id$
3
 *
4
 * Copyright (C) 2003
5
 *  Jamie Honan <jhonan@optusnet.com.au>
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
#include "config.h"
23
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#ifdef HAVE_STRINGS_H
28
#include <strings.h>
29
#endif
30
31
#include "scconf.h"
32
#include "internal.h"
33
34
typedef struct {
35
  char *buf;
36
  size_t bufmax;
37
  size_t bufcur;
38
  int saved_char;
39
  const char *saved_string;
40
  FILE *fp;
41
} BUFHAN;
42
43
static void buf_init(BUFHAN * bp, FILE * fp, const char *saved_string)
44
14.4k
{
45
14.4k
  bp->fp = fp;
46
14.4k
  bp->saved_char = 0;
47
14.4k
  bp->buf = malloc(256);
48
14.4k
  if (bp->buf) {
49
14.4k
    bp->bufmax = 256;
50
14.4k
    bp->buf[0] = '\0';
51
14.4k
  } else
52
0
    bp->bufmax = 0;
53
14.4k
  bp->bufcur = 0;
54
14.4k
  bp->saved_string = saved_string;
55
14.4k
}
56
57
static void buf_addch(BUFHAN * bp, char ch)
58
548k
{
59
548k
  if (bp->bufcur + 1 >= bp->bufmax) {
60
0
    char *p = (char *) realloc(bp->buf, bp->bufmax + 256);
61
0
    if (!p)
62
0
      return;
63
0
    bp->bufmax += 256;
64
0
    bp->buf = p;
65
0
  }
66
548k
  if (bp->buf) {
67
548k
    bp->buf[bp->bufcur++] = ch;
68
548k
    bp->buf[bp->bufcur] = '\0';
69
548k
  }
70
548k
}
71
72
static int buf_nextch(BUFHAN * bp)
73
736k
{
74
736k
  int saved;
75
76
736k
  if (bp->saved_char) {
77
72.1k
    saved = bp->saved_char;
78
72.1k
    bp->saved_char = 0;
79
72.1k
    return saved;
80
72.1k
  }
81
663k
  if (bp->saved_string) {
82
663k
    if (*(bp->saved_string) == '\0')
83
14.4k
      return EOF;
84
649k
    saved = (unsigned char) (*(bp->saved_string++));
85
649k
    return saved;
86
663k
  } else {
87
0
    saved = fgetc(bp->fp);
88
0
    return saved;
89
0
  }
90
663k
}
91
92
static void buf_finished(BUFHAN * bp)
93
14.4k
{
94
14.4k
  if (bp->buf) {
95
14.4k
    free(bp->buf);
96
14.4k
    bp->buf = NULL;
97
14.4k
  }
98
14.4k
}
99
100
static void buf_eat_till(BUFHAN * bp, char start, const char *end)
101
72.1k
{
102
72.1k
  int i;
103
104
72.1k
  if (start) {
105
72.1k
    buf_addch(bp, start);
106
72.1k
  }
107
476k
  while (1) {
108
476k
    i = buf_nextch(bp);
109
476k
    if (i == EOF)
110
0
      return;
111
476k
    if (strchr(end, i)) {
112
72.1k
      bp->saved_char = i;
113
72.1k
      return;
114
72.1k
    }
115
404k
    buf_addch(bp, (char) i);
116
404k
  }
117
72.1k
}
118
119
static void buf_zero(BUFHAN * bp)
120
144k
{
121
144k
  bp->bufcur = 0;
122
144k
  bp->buf[0] = '\0';
123
144k
}
124
125
static int scconf_lex_engine(scconf_parser * parser, BUFHAN * bp)
126
14.4k
{
127
14.4k
  int this_char;
128
129
259k
  while (1) {
130
259k
    switch (this_char = buf_nextch(bp)) {
131
0
    case '#':
132
      /* comment till end of line */
133
0
      buf_eat_till(bp, '#', "\r\n");
134
0
      scconf_parse_token(parser, TOKEN_TYPE_COMMENT, bp->buf);
135
0
      buf_zero(bp);
136
0
      continue;
137
0
    case '\n':
138
0
      scconf_parse_token(parser, TOKEN_TYPE_NEWLINE, NULL);
139
0
      continue;
140
101k
    case ' ':
141
101k
    case '\t':
142
101k
    case '\r':
143
      /* eat up whitespace */
144
101k
      continue;
145
14.4k
    case ',':
146
28.8k
    case '{':
147
28.8k
      if (parser->nested_blocks >= DEPTH_LIMIT) {
148
        /* reached the limit, this whole block */
149
0
        scconf_skip_block(parser);
150
0
        continue;
151
0
      }
152
      /* fall through */
153
43.2k
    case '}':
154
57.7k
    case '=':
155
72.1k
    case ';':
156
72.1k
      buf_addch(bp, (char) this_char);
157
72.1k
      scconf_parse_token(parser, TOKEN_TYPE_PUNCT, bp->buf);
158
72.1k
      buf_zero(bp);
159
72.1k
      continue;
160
0
    case '"':
161
0
      buf_eat_till(bp, (char) this_char, "\"\r\n");
162
0
      buf_addch(bp, (char) buf_nextch(bp));
163
0
      scconf_parse_token(parser, TOKEN_TYPE_STRING, bp->buf);
164
0
      buf_zero(bp);
165
0
      continue;
166
14.4k
    case EOF:
167
14.4k
      break;
168
72.1k
    default:
169
72.1k
      buf_eat_till(bp, (char) this_char, ";, \t\r\n");
170
72.1k
      scconf_parse_token(parser, TOKEN_TYPE_STRING, bp->buf);
171
72.1k
      buf_zero(bp);
172
72.1k
      continue;
173
259k
    }
174
14.4k
    break;
175
259k
  }
176
14.4k
  buf_finished(bp);
177
14.4k
  return 1;
178
14.4k
}
179
180
int scconf_lex_parse(scconf_parser * parser, const char *filename)
181
14.6k
{
182
14.6k
  FILE *fp;
183
14.6k
  BUFHAN bhan;
184
14.6k
  int ret;
185
186
14.6k
  fp = fopen(filename, "r");
187
14.6k
  if (!fp) {
188
14.6k
    parser->error = 1;
189
14.6k
    snprintf(parser->emesg, sizeof(parser->emesg),
190
14.6k
       "File %s can't be opened\n", filename);
191
14.6k
    return 0;
192
14.6k
  }
193
0
  buf_init(&bhan, fp, (char *) NULL);
194
0
  ret = scconf_lex_engine(parser, &bhan);
195
0
  fclose(fp);
196
0
  return ret;
197
14.6k
}
198
199
int scconf_lex_parse_string(scconf_parser * parser, const char *string)
200
14.4k
{
201
14.4k
  BUFHAN bhan;
202
14.4k
  int ret;
203
204
  buf_init(&bhan, (FILE *) NULL, string);
205
14.4k
  ret = scconf_lex_engine(parser, &bhan);
206
14.4k
  return ret;
207
14.4k
}