1 /*
2 netrik -- The ANTRIK Internet Viewer
3 Copyright (C) Olaf D. Buddenhagen AKA antrik, et al (see AUTHORS)
4 Published under the GNU GPL; see LICENSE for details.
5 */
6 /*
7 * parse-elements.c -- this one looks up the textual tags and parameters in the
8 * syntax tree and replaces them by enum numbers for further processing.
9 *
10 * (C) 2001 antrik
11 * 2002 Patrice
12 *
13 * It also contains a debug function which dumps all tag and parameter types to
14 * see if parse_tags recognized them correctly.
15 */
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19
20 #include "cfg.h"
21 #include "syntax.h"
22
23 /* look up the element and attriubte name strings to find out what kind they are */
parse_elements(syntax_tree)24 void parse_elements(syntax_tree)
25 struct Element *syntax_tree; /* top of syntax parse tree */
26 {
27 struct Element *cur_el; /* element currently processed */
28 int i;
29 int cur_attr; /* attribute currently processed */
30
31 #ifdef DEBUG
32 if(strcmp(element_table[EL_NO].name, "?")) { /* number of entries in "Element_type" enum doesn't match number of entries in "element_table[]" */
33 fprintf(stderr, "internal error: \"element_table[]\" broken\n");
34 exit(100);
35 } else if(strcmp(attr_table[ATTR_NO].name, "?")) {
36 fprintf(stderr, "internal error: \"attr_table[]\" broken\n");
37 exit(100);
38 }
39 #endif
40
41 syntax_tree->name.type=EL_GLOBAL; /* first element is always global element */
42
43 for(cur_el=syntax_tree->list_next; cur_el->parent!=NULL; cur_el=cur_el->list_next) { /* all elements in syntax parse tree */
44 if(cur_el->name.str!=NULL) { /* element has a name string */
45 /* search this element's name in table */
46 for(i=0; i<EL_NO; ++i)
47 if(!strcmp(cur_el->name.str, element_table[i].name)) /* found -> don't search further */
48 break;
49
50 if(cfg.warn_unknown) {
51 if(i==EL_NO) /* unknown element */
52 fprintf(stderr, "warning: ignoring unknown element: %s\n", cur_el->name.str);
53 }
54
55 free(cur_el->name.str);
56 cur_el->name.type=i; /* set type (==EL_NO if not found in table) */
57
58 for(cur_attr=0; cur_attr<cur_el->attr_count; ++cur_attr) { /* all attributes */
59 /* search this attributes's name in table */
60 for(i=0; i<ATTR_NO; ++i)
61 if(!strcmp(cur_el->attr[cur_attr].name.str, attr_table[i].name)) /* found -> don't search further */
62 break;
63
64 if(cfg.warn_unknown) {
65 if(i==ATTR_NO) /* unknown attribute */
66 fprintf(stderr, "warning: ignoring unknown attribute: %s\n", cur_el->attr[cur_attr].name.str);
67 }
68
69 free(cur_el->attr[cur_attr].name.str);
70 cur_el->attr[cur_attr].name.type=i; /* set type (==ATTR_NO if not found in table) */
71
72 /* avoid NULL values */
73 if(cur_el->attr[cur_attr].value.str==NULL) {
74 cur_el->attr[cur_attr].value.str=strdup("");
75 if(cur_el->attr[cur_attr].value.str==NULL) {
76 fprintf(stderr, "memory allocation error while parsing elements (in function parse_elements)\n");
77 exit(1);
78 }
79 }
80
81 /* Patrice --> */
82 /* convert to a number if there is a numeric value expected */
83 if(attr_table[i].numeric) {
84 char *tmpval=strdup(cur_el->attr[cur_attr].value.str);
85 free(cur_el->attr[cur_attr].value.str);
86 cur_el->attr[cur_attr].value.num=atoi(tmpval);
87 free(tmpval);
88 }
89 } /* for all attributes */
90
91 /* check if all mandatory attributes are set */
92 if(cur_el->name.type<EL_NO) { /* normal element (not EL_NO or EL_GLOBAL) -> check (avoids addign all non-mandatory attributes to dummy elements!) */
93 for(i=0; i<ATTR_NO; ++i) {
94 if(attr_table[i].def_val!=0 && attr_table[i].el==cur_el->name.type) {
95 for(cur_attr=0; cur_attr<cur_el->attr_count; ++cur_attr)
96 if((int)cur_el->attr[cur_attr].name.type==i) /* found -> don't search further */
97 break;
98 if(cur_attr==cur_el->attr_count) { /* need to add attribute */
99 cur_el->attr=realloc(cur_el->attr, (++cur_el->attr_count)*sizeof(struct Attr)); /* resize attribute array to hold new attribute */
100 if(cur_el->attr==NULL) {
101 fprintf(stderr, "memory allocation error while parsing elements (in function parse_elements)\n");
102 }
103 cur_el->attr[cur_el->attr_count-1].name.type=i;
104 if(attr_table[i].numeric)
105 cur_el->attr[cur_el->attr_count-1].value.num=atoi(attr_table[i].def_val);
106 else
107 cur_el->attr[cur_el->attr_count-1].value.str=strdup(attr_table[i].def_val);
108 }
109 }
110 }
111 } /* normal element */
112 /* <-- Patrice */
113
114 } else /* no name string => dummy element */
115 cur_el->name.type=EL_NO;
116 } /* for all elements */
117 }
118