Add forgotten files 1.4.70b
[polyglot.git] / parse.c
1
2 // parse.c
3
4 // includes
5
6 #include <string.h>
7
8 #include "parse.h"
9 #include "util.h"
10
11 // variables
12
13 char * Star[STAR_NUMBER];
14
15 // prototypes
16
17 static bool match_rec (char string[], const char pattern[], char * star[]);
18
19 // functions
20
21 // match()
22
23 bool match(char string[], const char pattern[]) {
24
25    ASSERT(string!=NULL);
26    ASSERT(pattern!=NULL);
27
28    ASSERT(strstr(pattern,"**")==NULL);
29
30    return match_rec(string,pattern,Star);
31 }
32
33 // match_rec()
34
35 static bool match_rec(char string[], const char pattern[], char * star[]) {
36
37    int c;
38
39    ASSERT(string!=NULL);
40    ASSERT(pattern!=NULL);
41    ASSERT(star!=NULL);
42
43    // iterative matches
44
45    while ((c=*pattern++) != '*') {
46       if (FALSE) {
47       } else if (c == '\0') { // end of pattern
48          while (*string == ' ') string++; // skip trailing spaces
49          return *string == '\0';
50       } else if (c == ' ') { // spaces
51          if (*string++ != ' ') return FALSE; // mismatch
52          while (*string == ' ') string++; // skip trailing spaces
53       } else { // normal character
54          if (*string++ != c) return FALSE; // mismatch
55       }
56    }
57
58    // recursive wildcard match
59
60    ASSERT(c=='*');
61
62    while (*string == ' ') string++; // skip leading spaces
63    *star++ = string; // remember beginning of star
64
65    while ((c=*string++) != '\0') { // reject empty-string match
66       if (c != ' ' && match_rec(string,pattern,star)) { // shortest match
67          ASSERT(string>star[-1]);
68          *string = '\0'; // truncate star
69          return TRUE;
70       }
71    }
72
73    return FALSE;
74 }
75
76 // parse_is_ok()
77
78 bool parse_is_ok(const parse_t * parse) {
79
80    if (parse == NULL) return FALSE;
81    if (parse->string == NULL) return FALSE;
82    if (parse->pos < 0 || parse->pos > (int) strlen(parse->string)) return FALSE;
83    if (parse->keyword_nb < 0 || parse->keyword_nb >= KEYWORD_NUMBER) return FALSE;
84
85    return TRUE;
86 }
87
88 // parse_open()
89
90 void parse_open(parse_t * parse, const char string[]) {
91
92    ASSERT(parse!=NULL);
93    ASSERT(string!=NULL);
94
95    parse->string = string;
96    parse->pos = 0;
97    parse->keyword_nb = 0;
98 }
99
100 // parse_close()
101
102 void parse_close(parse_t * parse) {
103
104    int i;
105
106    ASSERT(parse_is_ok(parse));
107
108    parse->string = NULL;
109    parse->pos = 0;
110
111    for (i = 0; i < parse->keyword_nb; i++) {
112       my_string_clear(&parse->keyword[i]);
113    }
114
115    parse->keyword_nb = 0;
116 }
117
118 // parse_add_keyword()
119
120 void parse_add_keyword(parse_t * parse, const char keyword[]) {
121
122    const char * * string;
123
124    ASSERT(parse_is_ok(parse));
125    ASSERT(keyword!=NULL);
126
127    if (parse->keyword_nb < KEYWORD_NUMBER) {
128
129       string = &parse->keyword[parse->keyword_nb];
130       parse->keyword_nb++;
131
132       *string = NULL;
133       my_string_set(string,keyword);
134    }
135 }
136
137 // parse_get_word()
138
139 bool parse_get_word(parse_t * parse, char string[], int size) {
140
141    int pos;
142    int c;
143
144    ASSERT(parse!=NULL);
145    ASSERT(string!=NULL);
146    ASSERT(size>=256);
147
148    // skip blanks
149
150    for (; parse->string[parse->pos] == ' '; parse->pos++)
151       ;
152
153    ASSERT(parse->string[parse->pos]!=' ');
154
155    // copy word
156
157    pos = 0;
158
159    while (TRUE) {
160
161       c = parse->string[parse->pos];
162       if (c == ' ' || pos >= size-1) c = '\0';
163
164       string[pos] = c;
165       if (c == '\0') break;
166
167       parse->pos++;
168       pos++;
169    }
170
171    ASSERT(strchr(string,' ')==NULL);
172
173    return pos > 0; // non-empty word?
174 }
175
176 // parse_get_string()
177
178 bool parse_get_string(parse_t * parse, char string[], int size) {
179
180    int pos;
181    parse_t parse_2[1];
182    char word[StringSize];
183    int i;
184    int c;
185
186    ASSERT(parse!=NULL);
187    ASSERT(string!=NULL);
188    ASSERT(size>=256);
189
190    // skip blanks
191
192    for (; parse->string[parse->pos] == ' '; parse->pos++)
193       ;
194
195    ASSERT(parse->string[parse->pos]!=' ');
196
197    // copy string
198
199    pos = 0;
200
201    while (TRUE) {
202
203       parse_open(parse_2,&parse->string[parse->pos]);
204
205       if (!parse_get_word(parse_2,word,StringSize)) {
206          string[pos] = '\0';
207          parse_close(parse_2);
208          goto finished;
209       }
210
211       for (i = 0; i < parse->keyword_nb; i++) {
212          if (my_string_equal(parse->keyword[i],word)) {
213             string[pos] = '\0';
214             parse_close(parse_2);
215             goto finished;
216          }
217       }
218
219       parse_close(parse_2);
220
221       // copy spaces
222
223       while (TRUE) {
224
225          c = parse->string[parse->pos];
226          if (c != ' ') break;
227
228          if (pos >= size-1) c = '\0';
229
230          string[pos] = c;
231          if (c == '\0') break;
232
233          parse->pos++;
234          pos++;
235       }
236
237       // copy non spaces
238
239       while (TRUE) {
240
241          c = parse->string[parse->pos];
242          if (c == ' ' || pos >= size-1) c = '\0';
243
244          string[pos] = c;
245          if (c == '\0') break;
246
247          parse->pos++;
248          pos++;
249       }
250
251       string[pos] = '\0';
252    }
253
254 finished: ;
255
256    return pos > 0; // non-empty string?
257 }
258
259 // end of parse.cpp
260