Used Variables instead of Options, in SConstruct
[mcc.git] / stree.c
blobc5af08c68fda8923f2694508d90799b2ae850b28
1 #include "stree.h"
2 #include "scanner.h"
3 #include "cc.h"
4 #include "errors.h"
5 #include "stdlib.h"
6 #include "stdio.h"
7 #include "string.h"
8 #include "assert.h"
9 #include "bstr.h"
11 static const char *form_strtab[] = {
12 "NONE",
13 "BINOP",
14 "UNOP",
15 "FACTOR",
16 "TAG",
17 "ATOM",
18 "TYPE",
19 "FUNCTION",
20 "VARIABLE",
21 "PARAMETERS",
22 "BLOCK",
23 "STAT",
24 "PASS",
25 "LABEL",
26 "JUMP",
29 static const char *storage_class_strtab[] = {
30 "",
31 " static",
32 " extern",
33 " common",
36 static int next_id = 1;
38 const char *stree_form_str(int form)
40 return form_strtab[form - STF_NONE];
43 const char *stree_storage_class_str(enum storage_class sc)
45 return storage_class_strtab[sc];
48 struct stree *stree_create(void)
50 struct stree *st;
51 st = emalloc(sizeof(struct stree));
52 memset(st, 0, sizeof (struct stree));
53 st->id = next_id++;
54 return st;
57 void stree_append_child(struct stree *st_parent, struct stree *st_child)
59 struct stree *st_child_prev = st_parent->child;
60 if (!st_parent || !st_child)
61 return;
62 st_child->parent = st_parent;
63 if (st_child_prev){
64 // insert at end of child list
65 while (st_child_prev->next){
66 st_child_prev = st_child_prev->next;
68 st_child_prev->next = st_child;
69 st_child->prev = st_child_prev;
70 st_child->next = NULL;
71 } else {
72 // first child
73 st_parent->child = st_child;
74 st_child->prev = NULL;
75 st_child->next = NULL;
79 void stree_remove_child(struct stree *st_child)
81 struct stree *st_parent = st_child->parent;
82 if (st_child->prev){
83 st_child->prev->next = st_child->next;
84 } else {
85 st_parent->child = st_child->next;
87 if (st_child->next){
88 st_child->next->prev = st_child->prev;
90 st_child->prev = NULL;
91 st_child->next = NULL;
92 st_child->parent = NULL;
95 void stree_destroy(struct stree *st)
97 if (st){
98 // destroy children
99 struct stree *st_child = st->child,
100 *st_child_next;
102 while (st_child){
103 st_child_next = st_child->next;
104 stree_destroy(st_child);
105 st_child = st_child_next;
108 if (st->cv.type == CBT_STRING){
109 free(st->cv.v.string);
111 free(st);
115 void stree_next_child(struct stree *st, struct stree **pchild)
117 if (*pchild == NULL){
118 *pchild = st->child;
119 } else {
120 *pchild = (*pchild)->next;
124 // form a string representing 'node', for debug output
125 static char *make_type_str(struct stree *node)
127 char *s = NULL;
128 // is the type info valid?
129 switch (node->form){
130 case STF_VARIABLE:
131 case STF_FUNCTION:
132 case STF_TYPE:
133 // XXX: erm, use arrays perhaps?
134 if (node->btype.qualifiers & TQ_RESTRICT)
135 strdcat(&s, "restrict ");
136 if (node->btype.qualifiers & TQ_VOLATILE)
137 strdcat(&s, "volatile ");
138 if (node->btype.qualifiers & TQ_CONST)
139 strdcat(&s, "const ");
140 if (node->btype.qualifiers & TQ_SIGNED)
141 strdcat(&s, "signed ");
142 if (node->btype.qualifiers & TQ_UNSIGNED)
143 strdcat(&s, "unsigned ");
144 if (node->btype.qualifiers & TQ_LONG_LONG)
145 strdcat(&s, "long long ");
146 if (node->btype.qualifiers & TQ_LONG)
147 strdcat(&s, "long ");
148 if (node->btype.qualifiers & TQ_SHORT)
149 strdcat(&s, "short ");
150 switch (node->btype.base_type){
151 case BT_VOID:
152 strdcat(&s, "void");
153 break;
154 case BT_CHAR:
155 strdcat(&s, "char");
156 break;
157 case BT_INT:
158 strdcat(&s, "int");
159 break;
160 case BT_FLOAT:
161 strdcat(&s, "float");
162 break;
163 case BT_DOUBLE:
164 strdcat(&s, "double");
165 break;
166 case BT_POINTER:
167 strdcat(&s, "pointer");
168 // TODO: pointing to what?
169 break;
170 case BT_STRUCT:
171 strdcat(&s, "struct");
172 // TODO: more informations!
173 break;
175 break;
176 default:
177 break;
179 return s;
182 static void stree_dump_internal(struct cc *cc, struct stree_stack *stack, FILE *output)
184 struct stree_stack stack_item;
186 // dump this node
187 struct stree_stack *p = stack;
188 assert(p);
189 // locate bottom of stack
190 while (p->prev){
191 p = p->prev;
193 while (p && p->next){
194 if (p->st_node->next){
195 fprintf(output, " | ");
196 } else {
197 fprintf(output, " ");
199 p = p->next;
201 if (stack->st_node->next){
202 fprintf(output, " +--");
203 } else {
204 fprintf(output, " L--");
207 char *type_str = make_type_str(stack->st_node);
208 fprintf(output, "%d:%s [%s]%s%s%s\n",
209 stack->st_node->id,
210 stree_form_str(stack->st_node->form),
211 lex_get_tok_str(&cc->lex, stack->st_node->tok, NULL),
212 stree_storage_class_str(stack->st_node->storage_class),
213 type_str ? " : " : "",
214 type_str ? type_str : "");
215 free(type_str);
218 // and the children
219 stack_item.prev = stack;
220 stack_item.next = NULL;
221 stack->next = &stack_item;
222 stack_item.st_node = stack->st_node->child;
223 while (stack_item.st_node){
224 stree_dump_internal(cc, &stack_item, output);
225 stack_item.st_node = stack_item.st_node->next;
227 stack->next = NULL; // pop stack
231 void stree_dump(struct cc *cc, struct stree *st_root, FILE *output)
233 struct stree_stack stack_item;
234 if (!st_root){
235 fprintf(output, "[TREE:NULL]\n");
236 return;
238 stack_item.st_node = st_root;
239 stack_item.prev = NULL;
240 stack_item.next = NULL;
241 stree_dump_internal(cc, &stack_item, output);
244 struct stree *stree_right(struct stree *st)
246 struct stree *p = st->child;
247 while (p && p->next){
248 p = p->next;
250 return p;
253 int stree_child_count(struct stree *st)
255 int n = 0;
256 struct stree *child_st;
257 if (!st){
258 return 0;
260 child_st = st->child;
261 while (child_st){
262 n++;
263 child_st = child_st->next;
265 return n;
268 struct stree *stree_find_local(struct stree *scope, enum stree_form form, tok_t tok)
270 if (!scope)
271 return NULL;
272 struct stree *p = scope->child;
273 while (p && !(p->form == form && p->tok == tok)){
274 p = p->next;
276 return p;
279 struct stree *stree_get_child_by_form(struct stree *st, enum stree_form form)
281 struct stree *child_st;
282 child_st = st->child;
283 while (child_st && child_st->form != form){
284 child_st = child_st->next;
286 return child_st;