2
* STFL - The Structured Terminal Forms Language/Library
3
* Copyright (C) 2006 Clifford Wolf <clifford@clifford.at>
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.
10
* This program is distributed in the hope that it will be useful,
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.
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
19
* parser.c: STFL Form description file parser
22
#include "stfl_internals.h"
28
static void extract_name(char **key, char **name)
30
int len = strcspn(*key, "[");
32
if ((*key)[len] == 0) {
37
*name = strdup(*key+len+1);
38
*key = realloc(*key, len+1);
41
len = strcspn(*name, "]");
45
static void extract_class(char **key, char **cls)
47
int len = strcspn(*key, "#");
49
if ((*key)[len] == 0) {
54
*cls = strdup(*key+len+1);
55
*key = realloc(*key, len+1);
59
static int read_type(const char **text, char **type, char **name, char **cls)
61
int len = strcspn(*text, " \t\r\n:{}");
63
if ((*text)[len] == ':' || len == 0)
66
*type = malloc(len+1);
67
memcpy(*type, *text, len);
71
extract_name(type, name);
72
extract_class(type, cls);
77
static int read_kv(const char **text, char **key, char **name, char **value)
79
int len_k = strcspn(*text, " \t\r\n:{}");
81
if ((*text)[len_k] != ':' || len_k == 0)
84
*key = malloc(len_k+1);
85
memcpy(*key, *text, len_k);
89
extract_name(key, name);
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')
95
if ((*text)[i] == '\'')
96
while ((*text)[++i] != '\'') len_v++;
98
if ((*text)[i] == '\"')
99
while ((*text)[++i] != '\"') len_v++;
104
*value = malloc(len_v+1);
107
while ((*text)[i] && (*text)[i] != ' ' && (*text)[i] != '{' && (*text)[i] != '}' &&
108
(*text)[i] != '\t' && (*text)[i] != '\r' && (*text)[i] != '\n')
110
if ((*text)[i] == '\'')
111
while ((*text)[++i] != '\'')
112
(*value)[j++] = (*text)[i];
114
if ((*text)[i] == '\"')
115
while ((*text)[++i] != '\"')
116
(*value)[j++] = (*text)[i];
118
(*value)[j++] = (*text)[i];
128
struct stfl_widget *stfl_parser(const char *text)
130
struct stfl_widget *root = 0;
131
struct stfl_widget *current = 0;
132
int bracket_indenting = -1;
133
int bracket_level = 0;
139
if (bracket_indenting >= 0)
141
while (*text == ' ' || *text == '\t') text++;
143
while (*text == '}') {
144
bracket_level--; text++;
145
while (*text == ' ' || *text == '\t') text++;
148
while (*text == '{') {
149
bracket_level++; text++;
150
while (*text == ' ' || *text == '\t') text++;
153
if (bracket_level == 0)
154
bracket_indenting = -1;
156
if (bracket_level < 0)
163
if (bracket_indenting >= 0)
165
while (*text == ' ' || *text == '\t')
168
if (*text == '\r' || *text == '\n')
171
indenting = bracket_indenting + (bracket_level-1);
175
while (*text == ' ' || *text == '\t' || *text == '\r' || *text == '\n') {
176
if (*text == '\r' || *text == '\n')
188
while (*text && *text != '\r' && *text != '\n')
194
bracket_indenting = indenting;
202
char *key, *name, *cls, *value;
208
int filename_len = strcspn(++text, ">");
209
char filename[filename_len+1];
211
memcpy(filename, text, filename_len);
212
filename[filename_len] = 0;
214
text += filename_len;
217
struct stfl_widget *n = stfl_parser_file(filename);
222
while (current->parser_indent >= indenting) {
223
current = current->parent;
229
if (current->last_child) {
230
current->last_child->next_sibling = n;
231
current->last_child = n;
233
current->first_child = n;
234
current->last_child = n;
237
n->parser_indent = indenting;
246
while (current->parser_indent >= indenting) {
247
current = current->parent;
252
if (read_type(&text, &key, &name, &cls) == 1)
254
struct stfl_widget *n = stfl_widget_new(key);
260
if (current->last_child) {
261
current->last_child->next_sibling = n;
262
current->last_child = n;
264
current->first_child = n;
265
current->last_child = n;
268
n->parser_indent = indenting;
274
if (read_kv(&text, &key, &name, &value) == 1)
276
struct stfl_kv *kv = stfl_widget_setkv_str(current, key, value);
289
if (read_type(&text, &key, &name, &cls) == 0)
292
struct stfl_widget *n = stfl_widget_new(key);
303
while (*text && *text != '\n' && *text != '\r' && *text != '{' && *text != '}')
305
while (*text == ' ' || *text == '\t')
308
if (*text && *text != '\n' && *text != '\r' && *text != '{' && *text != '}')
310
if (read_kv(&text, &key, &name, &value) == 0)
313
struct stfl_kv *kv = stfl_widget_setkv_str(current, key, value);
330
fprintf(stderr, "STFL Parser Error near '");
332
for (i=0; *text && i<20; i++, text++)
334
fprintf(stderr, "\\n");
337
fprintf(stderr, " ");
340
fprintf(stderr, "\\%03o", *text);
342
fprintf(stderr, "%c", *text);
344
fprintf(stderr, "'.\r\n");
350
struct stfl_widget *stfl_parser_file(const char *filename)
352
FILE *f = fopen(filename, "r");
355
fprintf(stderr, "STFL Parser Error: Can't read file '%s'!\n", filename);
365
text = realloc(text, len += 4096);
366
pos += fread(text+pos, 1, 4096, f);
374
struct stfl_widget *w = stfl_parser(text);