1 /**
2 *
3 * $Id: uillex.c,v 1.1 2004/08/28 19:22:42 dannybackx Exp $
4 *
5 * Copyright (C) 1995 Free Software Foundation, Inc.
6 * Copyright (C) 1995-2002 LessTif Development Team
7 *
8 * This file is part of the GNU LessTif Library.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25
26 static const char rcsid[] = "$Id: uillex.c,v 1.1 2004/08/28 19:22:42 dannybackx Exp $";
27
28 #include <LTconfig.h>
29
30 /* Enable this for verbose lexing */
31 /* #define DEBUG */
32
33 #include <stdlib.h>
34 #include <stdarg.h>
35 #include <string.h>
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <ctype.h>
39 #include <errno.h>
40 #ifdef HAVE_FCNTL_H
41 #include <fcntl.h>
42 #endif
43
44 #include <XmI/UilI.h>
45 #include <uil/UilSymGl.h>
46
47 #include <XmI/DebugUtil.h>
48
49
50 extern void
_uilmsg(Uil_parse_data * pd,int severity,const char * fmt,...)51 _uilmsg(Uil_parse_data *pd, int severity, const char *fmt, ...)
52 {
53 va_list arg_list;
54
55 va_start(arg_list, fmt);
56 vfprintf(stderr, fmt, arg_list);
57 va_end(arg_list);
58 }
59
60
61 static unsigned char
hashval(const char * data,int len)62 hashval(const char *data, int len)
63 {
64 int i;
65 unsigned char hash = 0;
66
67 for (i = 0; i < len; i++)
68 {
69 hash += data[i] * i;
70 }
71
72 hash %= sym_k_hash_table_limit;
73
74 return hash;
75 }
76
77
78 static sym_entry *
add_symbol(Uil_parse_data * pd,char * data,int len,int type)79 add_symbol(Uil_parse_data *pd, char *data, int len, int type)
80 {
81 int hash = hashval(data, len);
82 sym_entry *e, **lst;
83
84 e = (sym_entry *)XtMalloc(sizeof(sym_entry));
85
86 for (lst = &pd->hash[hash]; *lst != NULL; lst = &(*lst)->next)
87 ;
88
89 *lst = e;
90
91 e->next = NULL;
92 e->type = type;
93 e->text = XtMalloc(len);
94 e->len = len;
95 memcpy(e->text, data, len);
96 e->e.entry = NULL;
97
98 return e;
99 }
100
101
102 static sym_entry *
find_symbol(Uil_parse_data * pd,char * data,int len)103 find_symbol(Uil_parse_data *pd, char *data, int len)
104 {
105 int hash = hashval(data, len);
106 sym_entry *lst;
107
108 for (lst = pd->hash[hash]; lst != NULL; lst = lst->next)
109 {
110 if (lst->len == len && memcmp(lst->text, data, len) == 0)
111 {
112 return lst;
113 }
114 }
115
116 return NULL;
117 }
118
119
120 static void
add_file(Uil_parse_data * pd,char * fn)121 add_file(Uil_parse_data *pd, char *fn)
122 {
123 int i;
124
125 if (pd->files == NULL)
126 {
127 pd->max_files = 10;
128
129 pd->files = (char **)XtCalloc(pd->max_files, sizeof(char *));
130
131 pd->num_files = 0;
132
133 pd->cur_file_name_idx = 0;
134 }
135 else if (pd->num_files == pd->max_files - 1)
136 {
137 pd->max_files <<= 1;
138
139 pd->files = (char **)XtRealloc((char *)pd->files,
140 pd->max_files * sizeof(char *));
141 }
142
143 for (i = 0; i < pd->num_files; i++)
144 {
145 if (strcmp(fn, pd->files[i]) == 0)
146 {
147 pd->cur_file_name_idx = i;
148
149 return;
150 }
151 }
152
153 pd->files[pd->num_files] = XtNewString(fn);
154 pd->cur_file_name_idx = pd->num_files;
155 pd->num_files++;
156 }
157
158 static void
remove_file(Uil_parse_data * pd)159 remove_file(Uil_parse_data *pd)
160 {
161 if (pd->cur_file >= 0)
162 {
163 close(pd->cur_file);
164 pd->cur_file--;
165 }
166 }
167
168
169 static int
get_file(Uil_parse_data * pd,char * fn)170 get_file(Uil_parse_data *pd, char *fn)
171 {
172 int ret, i;
173
174 TRACE(("Trying to open %s\n", fn));
175
176 if ((ret = open(fn, O_RDONLY)) >= 0)
177 {
178 add_file(pd, fn);
179
180 pd->cur_file++;
181 pd->file_data[pd->cur_file].fd = ret;
182 pd->file_data[pd->cur_file].pbuf[PARSE_BUF_SIZE/2 - 1] = EOF;
183 pd->file_data[pd->cur_file].pbuf[PARSE_BUF_SIZE - 1] = EOF;
184 pd->file_data[pd->cur_file].lexeme = pd->file_data[pd->cur_file].pbuf;
185 pd->file_data[pd->cur_file].forward =
186 pd->file_data[pd->cur_file].pbuf + PARSE_BUF_SIZE - 2;
187
188 TRACE(("Opened file: cur_file is %d: fd %d\n",
189 pd->cur_file, pd->file_data[pd->cur_file].fd));
190
191 return ret;
192 }
193
194 for (i = 0; i < (int)pd->command->include_dir_count; i++)
195 {
196 char buf[PATHLENMAX];
197
198 strcpy(buf, pd->command->include_dir[i]);
199 if (buf[strlen(buf)] != '/')
200 {
201 strcat(buf, "/");
202 }
203
204 strcat(buf, fn);
205
206 TRACE(("Trying to open %s\n", fn));
207
208 if ((ret = open(buf, O_RDONLY)) > 0)
209 {
210 add_file(pd, buf);
211
212 pd->cur_file++;
213 pd->file_data[pd->cur_file].fd = ret;
214 pd->file_data[pd->cur_file].pbuf[PARSE_BUF_SIZE/2 - 1] = EOF;
215 pd->file_data[pd->cur_file].pbuf[PARSE_BUF_SIZE - 1] = EOF;
216 pd->file_data[pd->cur_file].lexeme =
217 pd->file_data[pd->cur_file].pbuf;
218 pd->file_data[pd->cur_file].forward =
219 pd->file_data[pd->cur_file].pbuf + PARSE_BUF_SIZE - 2;
220
221 return ret;
222 }
223 }
224
225 return -ENOENT;
226 }
227
228
229 extern Uil_parse_data *
_uil_parse_init(Uil_command_type * cmd,Uil_compile_desc_type * desc)230 _uil_parse_init(Uil_command_type *cmd, Uil_compile_desc_type *desc)
231 {
232 Uil_parse_data *pd;
233 int fd, i;
234
235 pd = (Uil_parse_data *)XtCalloc(1, sizeof(Uil_parse_data));
236
237 pd->command = cmd;
238 pd->desc = desc;
239 pd->root = NULL;
240 pd->hash = (sym_entry **)XtCalloc(sym_k_hash_table_limit,
241 sizeof(sym_entry *));
242
243 pd->cur_file = -1;
244 if ((fd = get_file(pd, cmd->source_file)) < 0)
245 {
246 _uilmsg(pd, Uil_k_severe_status,
247 "Can't open source file: %s\n", cmd->source_file);
248
249 _uil_parse_destroy(pd);
250
251 return NULL;
252 }
253
254 pd->include_depth = 0;
255
256 pd->num_lines = 0;
257 pd->max_lines = 100;
258 pd->lines =
259 (src_source_record_type *)XtCalloc(pd->max_lines,
260 sizeof(src_source_record_type));
261
262 for (i = 0; i < key_k_keyword_count; i++)
263 {
264 sym_entry *s;
265
266 s = add_symbol(pd, key_table[i].at_name, key_table[i].b_length,
267 KEYWORD);
268
269 s->e.keyword = &key_table[i];
270 }
271
272 return pd;
273 }
274
275
276 extern void
_uil_parse_destroy(Uil_parse_data * pd)277 _uil_parse_destroy(Uil_parse_data *pd)
278 {
279 int i;
280
281 if (pd->lines)
282 {
283 XtFree((char *)pd->lines);
284 }
285
286 if (pd->lines)
287 {
288 XtFree((char *)pd->lines);
289 }
290
291 if (pd->hash)
292 {
293 XtFree((char *)pd->hash);
294 }
295
296 if (pd->files)
297 {
298 for (i = 0; i < pd->num_files; i++)
299 {
300 XtFree(pd->files[i]);
301 }
302 XtFree((char *)pd->files);
303 }
304
305 XtFree((char *)pd);
306 }
307
308
309 static char
input(Uil_parse_data * pd)310 input(Uil_parse_data *pd)
311 {
312 int ret;
313 struct _file_data *cf = &pd->file_data[pd->cur_file];
314
315 cf->forward++;
316 cf->colno++;
317 if (*cf->forward == (char)EOF)
318 {
319 if (cf->forward - cf->pbuf == PARSE_BUF_SIZE - 1)
320 {
321 if ((ret = read(cf->fd, cf->pbuf,
322 PARSE_BUF_SIZE / 2 - 1)) < 0)
323 {
324 _uilmsg(pd, Uil_k_severe_status,
325 "Error reading source file: %s fd %d ret %d errno %d\n",
326 pd->files[pd->cur_file_name_idx],
327 pd->file_data[pd->cur_file].fd, ret, errno);
328
329 return EOF;
330 }
331 else if (ret < PARSE_BUF_SIZE / 2 - 1)
332 {
333 cf->forward = cf->pbuf;
334 cf->pbuf[ret] = EOF;
335
336 if (*cf->forward == '\n')
337 {
338 cf->lineno++;
339 cf->colno = 0;
340 }
341
342 return *cf->forward;
343 }
344 else
345 {
346 cf->forward = cf->pbuf;
347
348 if (*cf->forward == '\n')
349 {
350 cf->lineno++;
351 cf->colno = 0;
352 }
353
354 return *cf->forward;
355 }
356 }
357 else if (cf->forward - cf->pbuf == PARSE_BUF_SIZE / 2 - 1)
358 {
359 if ((ret = read(cf->fd, cf->pbuf + PARSE_BUF_SIZE / 2,
360 PARSE_BUF_SIZE / 2 - 1)) < 0)
361 {
362 _uilmsg(pd, Uil_k_severe_status,
363 "Error reading source file: %s fd %d ret %d errno %d\n",
364 pd->files[pd->cur_file_name_idx],
365 pd->file_data[pd->cur_file].fd, ret, errno);
366
367 return EOF;
368 }
369 else if (ret < PARSE_BUF_SIZE / 2 - 1)
370 {
371 cf->forward = cf->pbuf + PARSE_BUF_SIZE / 2;
372 cf->forward[ret] = EOF;
373
374 if (*cf->forward == '\n')
375 {
376 cf->lineno++;
377 cf->colno = 0;
378 }
379
380 return *cf->forward;
381 }
382 else
383 {
384 cf->forward = cf->pbuf + PARSE_BUF_SIZE / 2;
385
386 if (*cf->forward == '\n')
387 {
388 cf->lineno++;
389 cf->colno = 0;
390 }
391
392 return *cf->forward;
393 }
394 }
395 else
396 {
397 return EOF;
398 }
399 }
400
401 if (*cf->forward == '\n')
402 {
403 cf->lineno++;
404 cf->colno = 0;
405 }
406
407 return *cf->forward;
408 }
409
410
411 static void
unput(Uil_parse_data * pd)412 unput(Uil_parse_data *pd)
413 {
414 struct _file_data *cf = &pd->file_data[pd->cur_file];
415
416 if (*cf->forward == '\n')
417 {
418 cf->lineno--;
419 }
420
421 if (cf->forward == cf->pbuf)
422 {
423 cf->forward = cf->pbuf + PARSE_BUF_SIZE - 2;
424 }
425 else if (cf->forward == cf->pbuf + PARSE_BUF_SIZE / 2)
426 {
427 cf->forward = cf->pbuf + PARSE_BUF_SIZE / 2 - 2;
428 }
429 else
430 {
431 cf->forward--;
432 }
433 }
434
435
436 extern int
_uil_next_lexeme(Uil_parse_data * pd)437 _uil_next_lexeme(Uil_parse_data *pd)
438 {
439 char ch, ch2, *ptr;
440 int have_point;
441 sym_entry *e;
442
443 pd->file_data[pd->cur_file].lexeme = pd->file_data[pd->cur_file].forward;
444 for (;;)
445 {
446 ch = input(pd);
447
448 switch (ch)
449 {
450 case ' ':
451 case '\t':
452 case '\v':
453 case '\r':
454 case '\b':
455 case '\n':
456 /* skip it */
457 pd->file_data[pd->cur_file].lexeme =
458 pd->file_data[pd->cur_file].forward;
459 break;
460
461 case '!':
462 while ((ch = input(pd)) != '\n' && ch != (char)EOF)
463 ;
464
465 pd->file_data[pd->cur_file].lexeme =
466 pd->file_data[pd->cur_file].forward;
467
468 TRACE(("Bang comment: lineno: %d\n",
469 pd->file_data[pd->cur_file].lineno));
470
471 if (ch != '\n')
472 {
473 return EOF;
474 }
475 break;
476
477 case '/':
478 ch2 = input(pd);
479 if (ch2 == '*')
480 {
481 while ((ch2 = input(pd)) != (char)EOF)
482 {
483 if (ch2 == '*')
484 {
485 if ((ch = input(pd)) == '/')
486 {
487 pd->file_data[pd->cur_file].lexeme =
488 pd->file_data[pd->cur_file].forward;
489
490 break;
491 }
492 }
493 }
494
495 TRACE(("C comment: lineno: %d\n",
496 pd->file_data[pd->cur_file].lineno));
497
498 if (ch == (char)EOF)
499 {
500 return EOF;
501 }
502
503 pd->file_data[pd->cur_file].lexeme =
504 pd->file_data[pd->cur_file].forward;
505 }
506 else
507 {
508 unput(pd);
509
510 return ch;
511 }
512 break;
513
514 case '\'':
515 case '"':
516 ch2 = ch;
517 ptr = pd->curtok;
518 while ((ch = input(pd)) != (char)EOF)
519 {
520 if (ch == '\'' || ch == '"')
521 {
522 if (ch2 != '\\')
523 {
524 break;
525 }
526 }
527
528 *ptr = ch;
529 ptr++;
530 ch2 = ch;
531 }
532
533 if (ch == (char)EOF)
534 {
535 unput(pd);
536 }
537
538 *ptr = 0;
539
540 TRACE(("got STRING: %s\n", pd->curtok));
541
542 pd->value.string = XtNewString(pd->curtok);
543
544 return STRING;
545
546 case '*':
547 case '+':
548 case '-':
549 case '=':
550 TRACE(("got OPERATOR: %c\n", ch));
551 return ch;
552 break;
553
554 case '(':
555 case ')':
556 case '{':
557 case '}':
558 case ':':
559 case ';':
560 case ',':
561 TRACE(("got PUNCTUATION: %c\n", ch));
562 return ch;
563 break;
564
565 case '0': case '1': case '2': case '3': case '4':
566 case '5': case '6': case '7': case '8': case '9':
567 /* get number */
568 have_point = False;
569 ptr = pd->curtok;
570 *ptr = ch;
571 ptr++;
572 while ((ch = input(pd)) != (char)EOF)
573 {
574 if (!isdigit(ch) || ch != '.')
575 {
576 break;
577 }
578
579 if (ch == '.' && have_point)
580 {
581 break;
582 }
583 else if (ch == '.')
584 {
585 have_point = True;
586 }
587
588 *ptr = ch;
589 ptr++;
590 }
591
592 unput(pd);
593
594 *ptr = 0;
595
596 TRACE(("got NUMBER: %s\n", pd->curtok));
597
598 if (have_point)
599 {
600 pd->value.real = atof(pd->curtok);
601 return REAL;
602 }
603 else
604 {
605 pd->value.integer = atoi(pd->curtok);
606 return INT;
607 }
608
609 case EOF:
610 TRACE(("EOF\n"));
611 TRACE(("CURRENT FILE: %s line: %d\n",
612 pd->files[pd->cur_file_name_idx],
613 pd->file_data[pd->cur_file].lineno));
614
615 remove_file(pd);
616
617 if (pd->cur_file < 0)
618 {
619 return EOF;
620 }
621
622 break;
623
624 default:
625 if (isalpha(ch))
626 {
627 ptr = pd->curtok;
628 *ptr = ch;
629 ptr++;
630 while ((ch = input(pd)) != (char)EOF)
631 {
632 if (!isalpha(ch) && !isdigit(ch) && ch != '_')
633 {
634 break;
635 }
636 *ptr = ch;
637 ptr++;
638 }
639
640 unput(pd);
641
642 *ptr = 0;
643
644 TRACE(("got SYMBOL: %s\n", pd->curtok));
645
646 if ((e = find_symbol(pd, pd->curtok, strlen(pd->curtok)))
647 != NULL)
648 {
649 pd->value.sym = e;
650
651 return e->type;
652 }
653
654 pd->value.sym = add_symbol(pd, pd->curtok, strlen(pd->curtok),
655 SYMBOL);
656
657 return SYMBOL;
658 }
659 else
660 {
661 _uilmsg(pd, Uil_k_severe_status,
662 "Invalid lexical component: '%c' : %02x %s %d\n",
663 ch, (unsigned char)ch,
664 pd->files[pd->cur_file_name_idx],
665 pd->file_data[pd->cur_file].lineno);
666
667 return EOF;
668 }
669
670 break;
671 }
672 }
673 }
674