/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 | } |