~ubuntu-branches/ubuntu/intrepid/stfl/intrepid

« back to all changes in this revision

Viewing changes to parser.c

  • Committer: Bazaar Package Importer
  • Author(s): Nico Golde
  • Date: 2007-08-07 13:06:54 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070807130654-fmvsraotulj0nbri
Tags: 0.15-3
Again added fPIC to CFLAGS. Hopefully all build issues
are fixed now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *  STFL - The Structured Terminal Forms Language/Library
3
 
 *  Copyright (C) 2006  Clifford Wolf <clifford@clifford.at>
4
 
 *
5
 
 *  This program is free software; you can redistribute it and/or modify
6
 
 *  it under the terms of the GNU General Public License as published by
7
 
 *  the Free Software Foundation; either version 2 of the License, or
8
 
 *  (at your option) any later version.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
 
3
 *  Copyright (C) 2006, 2007  Clifford Wolf <clifford@clifford.at>
 
4
 *
 
5
 *  This library is free software; you can redistribute it and/or
 
6
 *  modify it under the terms of the GNU Lesser General Public
 
7
 *  License as published by the Free Software Foundation; either
 
8
 *  version 3 of the License, or (at your option) any later version.
 
9
 *  
 
10
 *  This library is distributed in the hope that it will be useful,
11
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 *  Lesser General Public License for more details.
 
14
 *  
 
15
 *  You should have received a copy of the GNU Lesser General Public
 
16
 *  License along with this library; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
18
 *  MA 02110-1301 USA
18
19
 *
19
20
 *  parser.c: STFL Form description file parser
20
21
 */
21
22
 
22
23
#include "stfl_internals.h"
 
24
#include "stfl_compat.h"
23
25
 
24
26
#include <stdio.h>
25
27
#include <string.h>
26
28
#include <stdlib.h>
27
 
 
28
 
static void extract_name(char **key, char **name)
29
 
{
30
 
        int len = strcspn(*key, "[");
 
29
#include <assert.h>
 
30
 
 
31
#define MYWCSCSPN_SKIP_QUOTED   0x01
 
32
#define MYWCSCSPN_SKIP_NAMES    0x02
 
33
 
 
34
static size_t mywcscspn(const wchar_t *wcs, const wchar_t *reject, int flags)
 
35
{
 
36
        enum {
 
37
                PLAIN,
 
38
                NAME_BLOCK,
 
39
                SINGLE_QUOTE,
 
40
                SINGLE_QUOTE_NAME,
 
41
                DOUBLE_QUOTE,
 
42
                DOUBLE_QUOTE_NAME,
 
43
        } state = PLAIN;
 
44
 
 
45
        int len = 0;
 
46
        int i;
 
47
 
 
48
        while (1)
 
49
        {
 
50
                if (!wcs[len])
 
51
                        return len;
 
52
 
 
53
                switch (state)
 
54
                {
 
55
                case PLAIN:
 
56
                        if ((flags & MYWCSCSPN_SKIP_NAMES) && (wcs[len] == L'[')) {
 
57
                                state = NAME_BLOCK;
 
58
                                break;
 
59
                        }
 
60
                        if ((flags & MYWCSCSPN_SKIP_QUOTED) && (wcs[len] == L'\'')) {
 
61
                                state = SINGLE_QUOTE;
 
62
                                break;
 
63
                        }
 
64
                        if ((flags & MYWCSCSPN_SKIP_QUOTED) && (wcs[len] == L'\"')) {
 
65
                                state = DOUBLE_QUOTE;
 
66
                                break;
 
67
                        }
 
68
                        for (i=0; reject[i]; i++)
 
69
                                if (wcs[len] == reject[i])
 
70
                                        return len;
 
71
                        break;
 
72
                case NAME_BLOCK:
 
73
                        if ((flags & MYWCSCSPN_SKIP_QUOTED) && (wcs[len] == L'\'')) {
 
74
                                state = SINGLE_QUOTE_NAME;
 
75
                                break;
 
76
                        }
 
77
                        if ((flags & MYWCSCSPN_SKIP_QUOTED) && (wcs[len] == L'\"')) {
 
78
                                state = DOUBLE_QUOTE_NAME;
 
79
                                break;
 
80
                        }
 
81
                        if (wcs[len] == L']')
 
82
                                state = PLAIN;
 
83
                        break;
 
84
                case SINGLE_QUOTE:
 
85
                case SINGLE_QUOTE_NAME:
 
86
                        if (wcs[len] == L'\'')
 
87
                                state = state == SINGLE_QUOTE ? PLAIN : NAME_BLOCK;
 
88
                        break;
 
89
                case DOUBLE_QUOTE:
 
90
                case DOUBLE_QUOTE_NAME:
 
91
                        if (wcs[len] == L'\"')
 
92
                                state = state == DOUBLE_QUOTE ? PLAIN : NAME_BLOCK;
 
93
                        break;
 
94
                }
 
95
 
 
96
                len++;
 
97
        }
 
98
}
 
99
 
 
100
static wchar_t *unquote(const wchar_t *text, int tlen)
 
101
{
 
102
        int len_v = 0, i, j;
 
103
        wchar_t *value;
 
104
 
 
105
        if (!text)
 
106
                return 0;
 
107
 
 
108
        for (i=0; text[i] && (i<tlen || tlen<0); i++)
 
109
        {
 
110
                if (text[i] == L'\'')
 
111
                        while (1) {
 
112
                                if (++i == tlen && tlen >= 0)
 
113
                                        goto finish_len_v_loop;
 
114
                                if (!text[i] || text[i] == L'\'') break;
 
115
                                len_v++;
 
116
                        }
 
117
                else
 
118
                if (text[i] == L'\"')
 
119
                        while (1) {
 
120
                                if (++i == tlen && tlen >= 0)
 
121
                                        goto finish_len_v_loop;
 
122
                                if (!text[i] || text[i] == L'\"') break;
 
123
                                len_v++;
 
124
                        }
 
125
                else
 
126
                        len_v++;
 
127
finish_len_v_loop:;
 
128
        }
 
129
 
 
130
        value = malloc(sizeof(wchar_t)*(len_v+1));
 
131
 
 
132
        for (i=j=0; text[i] && (i<tlen || tlen<0); i++)
 
133
        {
 
134
                if (text[i] == L'\'')
 
135
                        while (1) {
 
136
                                if (++i == tlen && tlen >= 0)
 
137
                                        goto finish_copy_loop;
 
138
                                if (!text[i] || text[i] == L'\'') break;
 
139
                                value[j++] = text[i];
 
140
                        }
 
141
                else
 
142
                if (text[i] == L'\"')
 
143
                        while (1) {
 
144
                                if (++i == tlen && tlen >= 0)
 
145
                                        goto finish_copy_loop;
 
146
                                if (!text[i] || text[i] == L'\"') break;
 
147
                                value[j++] = text[i];
 
148
                        }
 
149
                else
 
150
                        value[j++] = text[i];
 
151
finish_copy_loop:;
 
152
        }
 
153
 
 
154
        value[j] = 0;
 
155
        assert(j == len_v);
 
156
 
 
157
        return value;
 
158
}
 
159
 
 
160
static void extract_name(wchar_t **key, wchar_t **name)
 
161
{
 
162
        int len = wcscspn(*key, L"[");
31
163
 
32
164
        if ((*key)[len] == 0) {
33
165
                *name = 0;
34
166
                return;
35
167
        }
36
168
 
37
 
        *name = strdup(*key+len+1);
38
 
        *key = realloc(*key, len+1);
 
169
        *name = compat_wcsdup(*key+len+1);
 
170
        *key = realloc(*key, sizeof(wchar_t)*(len+1));
39
171
        (*key)[len] = 0;
40
172
 
41
 
        len = strcspn(*name, "]");
 
173
        len = mywcscspn(*name, L"]", MYWCSCSPN_SKIP_QUOTED);
42
174
        (*name)[len] = 0;
43
175
}
44
176
 
45
 
static void extract_class(char **key, char **cls)
 
177
static void extract_class(wchar_t **key, wchar_t **cls)
46
178
{
47
 
        int len = strcspn(*key, "#");
 
179
        int len = wcscspn(*key, L"#");
48
180
 
49
181
        if ((*key)[len] == 0) {
50
182
                *cls = 0;
51
183
                return;
52
184
        }
53
185
 
54
 
        *cls = strdup(*key+len+1);
55
 
        *key = realloc(*key, len+1);
 
186
        *cls = compat_wcsdup(*key+len+1);
 
187
        *key = realloc(*key, sizeof(wchar_t)*(len+1));
56
188
        (*key)[len] = 0;
57
189
}
58
190
 
59
 
static int read_type(const char **text, char **type, char **name, char **cls)
 
191
static int read_type(const wchar_t **text, wchar_t **type, wchar_t **name, wchar_t **cls)
60
192
{
61
 
        int len = strcspn(*text, " \t\r\n:{}");
 
193
        int len = mywcscspn(*text, L" \t\r\n:{}", MYWCSCSPN_SKIP_QUOTED|MYWCSCSPN_SKIP_NAMES);
62
194
 
63
 
        if ((*text)[len] == ':' || len == 0)
 
195
        if ((*text)[len] == L':' || len == 0)
64
196
                return 0;
65
197
 
66
 
        *type = malloc(len+1);
67
 
        memcpy(*type, *text, len);
 
198
        *type = malloc((len+1)*sizeof(wchar_t));
 
199
        wmemcpy(*type, *text, len);
68
200
        (*type)[len] = 0;
69
201
        *text += len;
70
202
 
74
206
        return 1;
75
207
}
76
208
 
77
 
static int read_kv(const char **text, char **key, char **name, char **value)
 
209
static int read_kv(const wchar_t **text, wchar_t **key, wchar_t **name, wchar_t **value)
78
210
{
79
 
        int len_k = strcspn(*text, " \t\r\n:{}");
 
211
        int len_k = mywcscspn(*text, L" \t\r\n:{}", MYWCSCSPN_SKIP_QUOTED|MYWCSCSPN_SKIP_NAMES);
80
212
 
81
 
        if ((*text)[len_k] != ':' || len_k == 0)
 
213
        if ((*text)[len_k] != L':' || len_k == 0)
82
214
                return 0;
83
215
 
84
 
        *key = malloc(len_k+1);
85
 
        memcpy(*key, *text, len_k);
 
216
        *key = malloc((len_k+1)*sizeof(wchar_t));
 
217
        wmemcpy(*key, *text, len_k);
86
218
        (*key)[len_k] = 0;
87
219
        *text += len_k+1;
88
220
 
89
221
        extract_name(key, name);
90
222
 
91
 
        int len_v = 0, i = 0, j = 0;
92
 
        while ((*text)[i] && (*text)[i] != ' ' && (*text)[i] != '{' && (*text)[i] != '}' &&
93
 
               (*text)[i] != '\t' && (*text)[i] != '\r' && (*text)[i] != '\n')
94
 
        {
95
 
                if ((*text)[i] == '\'')
96
 
                        while ((*text)[++i] != '\'') len_v++;
97
 
                else
98
 
                if ((*text)[i] == '\"')
99
 
                        while ((*text)[++i] != '\"') len_v++;
100
 
                len_v++;
101
 
                i++;
102
 
        }
103
 
 
104
 
        *value = malloc(len_v+1);
105
 
        i = 0;
106
 
 
107
 
        while ((*text)[i] && (*text)[i] != ' ' && (*text)[i] != '{' && (*text)[i] != '}' &&
108
 
               (*text)[i] != '\t' && (*text)[i] != '\r' && (*text)[i] != '\n')
109
 
        {
110
 
                if ((*text)[i] == '\'')
111
 
                        while ((*text)[++i] != '\'')
112
 
                                (*value)[j++] = (*text)[i];
113
 
                else
114
 
                if ((*text)[i] == '\"')
115
 
                        while ((*text)[++i] != '\"')
116
 
                                (*value)[j++] = (*text)[i];
117
 
                else
118
 
                        (*value)[j++] = (*text)[i];
119
 
                i++;
120
 
        }
121
 
        
122
 
        (*value)[j] = 0;
123
 
        *text += i;
 
223
        int qval_len = mywcscspn(*text, L" \t\r\n{}", MYWCSCSPN_SKIP_QUOTED);
 
224
        *value = unquote(*text, qval_len);
 
225
        *text += qval_len;
124
226
 
125
227
        return 1;
126
228
}
127
229
 
128
 
struct stfl_widget *stfl_parser(const char *text)
 
230
struct stfl_widget *stfl_parser(const wchar_t *text)
129
231
{
130
232
        struct stfl_widget *root = 0;
131
233
        struct stfl_widget *current = 0;
138
240
 
139
241
                if (bracket_indenting >= 0)
140
242
                {
141
 
                        while (*text == ' ' || *text == '\t') text++;
 
243
                        while (*text == L' ' || *text == L'\t') text++;
142
244
 
143
 
                        while (*text == '}') {
 
245
                        while (*text == L'}') {
144
246
                                bracket_level--; text++;
145
 
                                while (*text == ' ' || *text == '\t') text++;
 
247
                                while (*text == L' ' || *text == L'\t') text++;
146
248
                        }
147
249
 
148
 
                        while (*text == '{') {
 
250
                        while (*text == L'{') {
149
251
                                bracket_level++; text++;
150
 
                                while (*text == ' ' || *text == '\t') text++;
 
252
                                while (*text == L' ' || *text == L'\t') text++;
151
253
                        }
152
254
 
153
255
                        if (bracket_level == 0)
157
259
                                goto parser_error;
158
260
                }
159
261
                else
160
 
                        if (*text == '}')
 
262
                        if (*text == L'}')
161
263
                                goto parser_error;
162
264
 
163
265
                if (bracket_indenting >= 0)
164
266
                {
165
 
                        while (*text == ' ' || *text == '\t')
 
267
                        while (*text == L' ' || *text == L'\t')
166
268
                                text++;
167
269
 
168
 
                        if (*text == '\r' || *text == '\n')
 
270
                        if (*text == L'\r' || *text == L'\n')
169
271
                                goto parser_error;
170
272
 
171
273
                        indenting = bracket_indenting + (bracket_level-1);
172
274
                }
173
275
                else
174
276
                {
175
 
                        while (*text == ' ' || *text == '\t' || *text == '\r' || *text == '\n') {
176
 
                                if (*text == '\r' || *text == '\n')
 
277
                        while (*text == L' ' || *text == L'\t' || *text == L'\r' || *text == L'\n') {
 
278
                                if (*text == L'\r' || *text == L'\n')
177
279
                                        indenting = 0;
178
280
                                else
179
 
                                if (*text == '\t')
 
281
                                if (*text == L'\t')
180
282
                                        indenting = -1;
181
283
                                else
182
284
                                if (indenting >= 0)
184
286
                                text++;
185
287
                        }
186
288
 
187
 
                        if (*text == '*') {
188
 
                                while (*text && *text != '\r' && *text != '\n')
 
289
                        if (*text == L'*') {
 
290
                                while (*text && *text != L'\r' && *text != L'\n')
189
291
                                        text++;
190
292
                                continue;
191
293
                        }
192
294
 
193
 
                        if (*text == '{') {
 
295
                        if (*text == L'{') {
194
296
                                bracket_indenting = indenting;
195
297
                                continue;
196
298
                        }
199
301
                if (*text == 0)
200
302
                        break;
201
303
 
202
 
                char *key, *name, *cls, *value;
 
304
                wchar_t *key, *name, *cls, *value;
203
305
                if (indenting < 0)
204
306
                        goto parser_error;
205
307
 
206
 
                if (*text == '<')
 
308
                if (*text == L'<')
207
309
                {
208
 
                        int filename_len = strcspn(++text, ">");
209
 
                        char filename[filename_len+1];
210
 
 
211
 
                        memcpy(filename, text, filename_len);
212
 
                        filename[filename_len] = 0;
 
310
                        int filename_len = wcscspn(++text, L">");
 
311
                        wchar_t wfn[filename_len+1];
 
312
 
 
313
                        wmemcpy(wfn, text, filename_len+1);
 
314
                        wfn[filename_len] = 0;
 
315
 
 
316
                        size_t len = wcstombs(NULL,wfn,0)+1;
 
317
                        char filename[len];
 
318
                        size_t rc = wcstombs(filename, wfn, len);
 
319
                        assert(rc != (size_t)-1);
213
320
 
214
321
                        text += filename_len;
215
322
                        if (*text) text++;
266
373
                                }
267
374
 
268
375
                                n->parser_indent = indenting;
269
 
                                n->name = name;
 
376
                                n->name = unquote(name, -1);
 
377
                                free(name);
270
378
                                n->cls = cls;
271
379
                                current = n;
272
380
                        }
276
384
                                struct stfl_kv *kv = stfl_widget_setkv_str(current, key, value);
277
385
                                if (kv->name)
278
386
                                        free(kv->name);
279
 
                                kv->name = name;
 
387
                                kv->name = unquote(name, -1);
 
388
                                free(name);
280
389
 
281
390
                                free(key);
282
391
                                free(value);
296
405
 
297
406
                        root = n;
298
407
                        current = n;
299
 
                        n->name = name;
 
408
                        n->name = unquote(name, -1);
 
409
                        free(name);
300
410
                        n->cls = cls;
301
411
                }
302
412
 
303
 
                while (*text && *text != '\n' && *text != '\r' && *text != '{' && *text != '}')
 
413
                while (*text && *text != L'\n' && *text != L'\r' && *text != L'{' && *text != L'}')
304
414
                {
305
 
                        while (*text == ' ' || *text == '\t')
 
415
                        while (*text == L' ' || *text == L'\t')
306
416
                                text++;
307
417
 
308
 
                        if (*text && *text != '\n' && *text != '\r' && *text != '{' && *text != '}')
 
418
                        if (*text && *text != L'\n' && *text != L'\r' && *text != L'{' && *text != L'}')
309
419
                        {
310
420
                                if (read_kv(&text, &key, &name, &value) == 0)
311
421
                                        goto parser_error;
313
423
                                struct stfl_kv *kv = stfl_widget_setkv_str(current, key, value);
314
424
                                if (kv->name)
315
425
                                        free(kv->name);
316
 
                                kv->name = name;
 
426
                                kv->name = unquote(name, -1);
 
427
                                free(name);
317
428
 
318
429
                                free(key);
319
430
                                free(value);
330
441
        fprintf(stderr, "STFL Parser Error near '");
331
442
 
332
443
        for (i=0; *text && i<20; i++, text++)
333
 
                if (*text == '\n')
 
444
                if (*text == L'\n')
334
445
                        fprintf(stderr, "\\n");
335
446
                else
336
 
                if (*text == '\t')
 
447
                if (*text == L'\t')
337
448
                        fprintf(stderr, " ");
338
449
                else
339
450
                if (*text < 32)
340
 
                        fprintf(stderr, "\\%03o", *text);
 
451
                        fprintf(stderr, "\\%03lo", *text);
341
452
                else
342
 
                        fprintf(stderr, "%c", *text);
 
453
                        fprintf(stderr, "%lc", (wint_t)*text);
343
454
 
344
455
        fprintf(stderr, "'.\r\n");
345
456
        abort();
371
482
                }
372
483
        }
373
484
 
374
 
        struct stfl_widget *w = stfl_parser(text);
 
485
        const char * text1 = text;
 
486
        size_t wtextsize = mbsrtowcs(NULL,&text1,strlen(text1)+1,NULL)+1;
 
487
        wchar_t * wtext = malloc(sizeof(wchar_t)*wtextsize);
 
488
 
 
489
        size_t rc = mbstowcs(wtext, text, wtextsize);
 
490
        assert(rc != (size_t)-1);
 
491
 
 
492
#if 0
 
493
        fprintf(stderr,"strlen(text) = %u wcslen(wtext) = %u rc = %u wtextsize = %u\n", strlen(text), wcslen(wtext), rc, wtextsize);
 
494
        fprintf(stderr,"this is where is fucked up: `%lc' `%lc' `%lc' `%lc' `%lc'\n",text1[0],text1[1],text1[2],text1[3],text1[4]);
 
495
        fprintf(stderr,"original: `%s'\n", text);
 
496
        fprintf(stderr,"converted: `%ls'\n", wtext);
 
497
#endif
 
498
 
 
499
        struct stfl_widget *w = stfl_parser(wtext);
375
500
        free(text);
 
501
        free(wtext);
376
502
 
377
503
        return w;
378
504
}