Coverage Report

Created: 2026-03-08 07:02

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
13.9k
{
45
13.9k
  bp->fp = fp;
46
13.9k
  bp->saved_char = 0;
47
13.9k
  bp->buf = malloc(256);
48
13.9k
  if (bp->buf) {
49
13.9k
    bp->bufmax = 256;
50
13.9k
    bp->buf[0] = '\0';
51
13.9k
  } else
52
0
    bp->bufmax = 0;
53
13.9k
  bp->bufcur = 0;
54
13.9k
  bp->saved_string = saved_string;
55
13.9k
}
56
57
static void buf_addch(BUFHAN * bp, char ch)
58
531k
{
59
531k
  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
531k
  if (bp->buf) {
67
531k
    bp->buf[bp->bufcur++] = ch;
68
531k
    bp->buf[bp->bufcur] = '\0';
69
531k
  }
70
531k
}
71
72
static int buf_nextch(BUFHAN * bp)
73
713k
{
74
713k
  int saved;
75
76
713k
  if (bp->saved_char) {
77
69.9k
    saved = bp->saved_char;
78
69.9k
    bp->saved_char = 0;
79
69.9k
    return saved;
80
69.9k
  }
81
643k
  if (bp->saved_string) {
82
643k
    if (*(bp->saved_string) == '\0')
83
13.9k
      return EOF;
84
629k
    saved = (unsigned char) (*(bp->saved_string++));
85
629k
    return saved;
86
643k
  } else {
87
0
    saved = fgetc(bp->fp);
88
0
    return saved;
89
0
  }
90
643k
}
91
92
static void buf_finished(BUFHAN * bp)
93
13.9k
{
94
13.9k
  if (bp->buf) {
95
13.9k
    free(bp->buf);
96
13.9k
    bp->buf = NULL;
97
13.9k
  }
98
13.9k
}
99
100
static void buf_eat_till(BUFHAN * bp, char start, const char *end)
101
69.9k
{
102
69.9k
  int i;
103
104
69.9k
  if (start) {
105
69.9k
    buf_addch(bp, start);
106
69.9k
  }
107
461k
  while (1) {
108
461k
    i = buf_nextch(bp);
109
461k
    if (i == EOF)
110
0
      return;
111
461k
    if (strchr(end, i)) {
112
69.9k
      bp->saved_char = i;
113
69.9k
      return;
114
69.9k
    }
115
391k
    buf_addch(bp, (char) i);
116
391k
  }
117
69.9k
}
118
119
static void buf_zero(BUFHAN * bp)
120
139k
{
121
139k
  bp->bufcur = 0;
122
139k
  bp->buf[0] = '\0';
123
139k
}
124
125
static int scconf_lex_engine(scconf_parser * parser, BUFHAN * bp)
126
13.9k
{
127
13.9k
  int this_char;
128
129
251k
  while (1) {
130
251k
    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
97.8k
    case ' ':
141
97.8k
    case '\t':
142
97.8k
    case '\r':
143
      /* eat up whitespace */
144
97.8k
      continue;
145
13.9k
    case ',':
146
27.9k
    case '{':
147
27.9k
      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
41.9k
    case '}':
154
55.9k
    case '=':
155
69.9k
    case ';':
156
69.9k
      buf_addch(bp, (char) this_char);
157
69.9k
      scconf_parse_token(parser, TOKEN_TYPE_PUNCT, bp->buf);
158
69.9k
      buf_zero(bp);
159
69.9k
      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
13.9k
    case EOF:
167
13.9k
      break;
168
69.9k
    default:
169
69.9k
      buf_eat_till(bp, (char) this_char, ";, \t\r\n");
170
69.9k
      scconf_parse_token(parser, TOKEN_TYPE_STRING, bp->buf);
171
69.9k
      buf_zero(bp);
172
69.9k
      continue;
173
251k
    }
174
13.9k
    break;
175
251k
  }
176
13.9k
  buf_finished(bp);
177
13.9k
  return 1;
178
13.9k
}
179
180
int scconf_lex_parse(scconf_parser * parser, const char *filename)
181
13.9k
{
182
13.9k
  FILE *fp;
183
13.9k
  BUFHAN bhan;
184
13.9k
  int ret;
185
186
13.9k
  fp = fopen(filename, "r");
187
13.9k
  if (!fp) {
188
13.9k
    parser->error = 1;
189
13.9k
    snprintf(parser->emesg, sizeof(parser->emesg),
190
13.9k
       "File %s can't be opened\n", filename);
191
13.9k
    return 0;
192
13.9k
  }
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
13.9k
}
198
199
int scconf_lex_parse_string(scconf_parser * parser, const char *string)
200
13.9k
{
201
13.9k
  BUFHAN bhan;
202
13.9k
  int ret;
203
204
  buf_init(&bhan, (FILE *) NULL, string);
205
13.9k
  ret = scconf_lex_engine(parser, &bhan);
206
13.9k
  return ret;
207
13.9k
}