Added package with the documentation and the examples
[lwc.git] / cdb.c
blob150ff4feff98e90e51c17ad54f37dda5f6440e6a
1 #include "global.h"
3 /******************************************************************************
4 enumeration constants
5 only interested for the existance and not the actual value
6 ******************************************************************************/
8 static intnode *enumconsttree;
10 void enter_enumconst (Token e, enumID id)
12 if (intfind (enumconsttree, e))
13 parse_error_ll ("enumeration constant redef");
14 union ival i = { .i = id };
15 intadd (&enumconsttree, e, i);
18 int is_enumconst (Token e)
20 return intfind (enumconsttree, e) != NULL;
23 enumID id_of_enumconst (Token e)
25 return intfind (enumconsttree, e)->v.i;
28 /******************************************************************************
29 enum tags:
30 only interested for the existance of an enum tag
31 ******************************************************************************/
33 static intnode *enumtree;
34 static int en_inc;
36 enumID enter_enum (Token e)
38 intnode *n;
39 if (n = intfind (enumtree, e))
40 return n->v.i;
41 union ival i = { .i = en_inc };
42 intadd (&enumtree, e, i);
43 return en_inc++;
46 enumID lookup_enum (Token e)
48 intnode *n = intfind (enumtree, e);
49 return n ? n->v.i : -1;
52 static intnode *enumsyms;
54 void enter_enum_syms (enumID id, Token ev[], int n)
56 if (intfind (enumsyms, id))
57 parse_error_ll ("enum redefined");
58 union ival i = { .p = memcpy (mallocint (n), ev, n * sizeof ev [0]) };
59 intadd (&enumsyms, id, i);
62 Token *enum_syms (enumID e)
64 intnode *n = intfind (enumsyms, e);
65 return n ? (Token*) n->v.p + 1 : 0;
68 /******************************************************************************
69 typedef:
70 store/return the type of it
71 if a typedef is used, print it in GLOBAL
72 ******************************************************************************/
74 static intnode *typedeftree;
76 bool enter_typedef (Token e, typeID t)
78 #ifdef DEBUG
79 if (debugflag.TDEF_TRACE)
80 PRINTF ("Enter typedef ["COLS"%s"COLE"]\n", expand (e));
81 #endif
82 intnode *n;
83 if ((n = intfind (typedeftree, e))) {
84 if (n->v.i != t)
85 parse_error_ll ("typedef redef");
86 return 0;
88 union ival i = { .i = t };
89 intadd (&typedeftree, e, i);
90 return 1;
93 typeID lookup_typedef (Token e)
95 intnode *n = intfind (typedeftree, e);
96 return n ? n->v.i : -1;
99 /******************************************************************************
100 new/delete overloaders
101 a simple dictionary or class:new_func and another class:del_func
102 ******************************************************************************/
104 static intnode *new_tree, *delete_tree;
106 Token new_wrap = RESERVED_malloc, delete_wrap = RESERVED_free;
108 void enter_newdel_overload (Token a, recID r, Token fn)
110 union ival i = { .i = fn };
111 intadd (a == RESERVED_new ? &new_tree : &delete_tree, r, i);
114 Token lookup_newdel_operator (Token a, recID r)
116 intnode *n = intfind (a == RESERVED_new ? new_tree : delete_tree, r);
117 return n ? n->v.i : 0;
120 /******************************************************************************
121 abstract classes:
122 - store location of declaration and parents
123 - store location of functions declared outside the class
124 - store classes that inherit from it
125 Finally, do for each template class: for each derrived class:
126 reparse all functions declared outside the body of the class.
127 ******************************************************************************/
129 static intnode *abstracttree;
131 typedef struct {
132 Token name;
133 Token *par;
134 recID *rpar;
135 NormPtr p;
136 recID *der;
137 bool *derd;
138 int nder;
139 NormPtr *ext;
140 int next;
141 } ainfo;
143 void enter_abstract (Token a, Token *par, Token *rpar, NormPtr p)
145 if (is_struct (a))
146 parse_error (p, "Already have a class named that");
148 if (intfind (abstracttree, a))
149 parse_error_tok (a, "abstract class redeclared");
151 int i;
153 for (i = 0; par [i] != -1; i++)
154 if (!intfind (abstracttree, par [i]))
155 parse_error_tok (par [i], "No such abstract class to inherit");
157 ainfo *A = (ainfo*) malloc (sizeof (ainfo));
158 A->name = a;
159 A->p = p;
160 A->par = intdup (par);
161 A->rpar = intdup (rpar);
162 A->nder = 0;
163 A->der = 0;
164 A->derd = 0;
165 A->next = 0;
166 A->ext = 0;
167 union ival u = { .p = A };
168 intadd (&abstracttree, a, u);
171 void enter_abstract_derrived (Token a, recID der)
173 ainfo *n = (ainfo*) intfind (abstracttree, a)->v.p;
175 if (n->nder % 32 == 0) {
176 n->der = (recID*) realloc (n->der, sizeof (recID) * (n->nder + 32));
177 n->derd = (bool*) realloc (n->derd, sizeof (bool) * (n->nder + 32));
179 n->derd [n->nder] = false;
180 n->der [n->nder++] = der;
183 void enter_abstract_external (Token a, NormPtr p)
185 ainfo *n = (ainfo*) intfind (abstracttree, a)->v.p;
187 if (n->next % 32 == 0)
188 n->ext = (recID*) realloc (n->ext, sizeof (recID) * (n->next + 32));
189 n->ext [n->next++] = p;
192 bool abstract_has_special (Token a, recID spec)
194 ainfo *n = (ainfo*) intfind (abstracttree, a)->v.p;
195 int i;
197 for (i = 0; i < n->nder; i++)
198 if (n->der [i] == spec)
199 return true;
200 return false;
203 bool have_abstract (Token a)
205 return intfind (abstracttree, a) != 0;
208 int real_abstract_parents (Token a, recID ip [])
210 int i, j;
211 intnode *n = intfind (abstracttree, a);
212 Token *pp = ((ainfo*) n->v.p)->par;
214 for (i = j = 0; pp [j] != -1; j++)
215 i += real_abstract_parents (pp [j], &ip [i]);
216 recID *rp = ((ainfo*) n->v.p)->rpar;
217 for (j = 0; rp [j] != -1; j++)
218 ip [i++] = rp [j];
219 ip [i] = -1;
220 return i;
223 NormPtr dcl_of_abstract (Token a)
225 intnode *n = intfind (abstracttree, a);
226 return n ? ((ainfo*) n->v.p)->p : -1;
229 Token *parents_of_abstract (Token a)
231 intnode *n = intfind (abstracttree, a);
232 return n ? ((ainfo*) n->v.p)->par : 0;
235 static bool do_for_class (intnode *n)
237 ainfo *a = (ainfo*) n->v.p;
238 int i, j;
239 bool r = false;
241 if (a->next)
242 for (i = 0; i < a->nder; i++)
243 if (!a->derd [i]) {
244 for (j = 0; j < a->next; j++)
245 reparse_template_func (a->name, a->der [i], a->ext [j]);
246 a->derd [i] = true;
247 r = true;
250 if (n->less) r |= do_for_class (n->less);
251 if (n->more) r |= do_for_class (n->more);
252 return r;
255 bool specialize_abstracts ()
257 return abstracttree ? do_for_class (abstracttree) : false;
259 /******************************************************************************
260 type IDs
261 store/return the type string of a typeID
262 ******************************************************************************/
264 static int **types;
265 static int ntypes, nalloc;
267 typeID enter_type (int *ts)
269 int i;
270 for (i = 0; i < ntypes; i++)
271 if (!intcmp (types [i], ts))
272 return i;
273 if (ntypes == nalloc)
274 types = (int**) realloc (types, (nalloc += 64) * sizeof (int*));
275 types [ntypes] = intdup (ts);
276 return ntypes++;
279 int *open_typeID (typeID t)
281 return types [t];
284 bool isfunction (typeID t)
286 return open_typeID (t) [1] == '(';
289 bool typeID_elliptic (typeID t)
291 return open_typeID (t) [1] == B_ELLIPSIS;
294 //++++++++++++++++++++++++++++++++++++++++++++
295 typeID typeID_NOTYPE, typeID_int, typeID_float, typeID_charP,
296 typeID_voidP, typeID_void, typeID_uint, typeID_ebn_f, typeID_intP;
298 /******************************************************************************
299 is_typename, returns:
300 0: is not
301 1: is typedef
302 2: is a structure without 'struct'
303 3: is enum without 'enum'
304 SYMBOL: it is a local typedef translated
305 ******************************************************************************/
307 int is_typename (Token t)
309 int i;
310 Token l;
312 if (lookup_typedef (t) != -1) return 1;
313 if (is_struct (t)) return 2;
314 if (is_enum (t)) return 3;
315 for (i = top_scope; i; --i)
316 if (l = lookup_local_typedef (current_scope [i], t))
317 return l;
318 return 0;
321 bool is_dcl_start (Token t)
323 if (ISRESERVED (t))
324 return ISAGGRSPC (t) || t == RESERVED_specialize || t == RESERVED_RegExp
325 || t == RESERVED_typeof || ISTBASETYPE(t) || ISDCLFLAG(t);
326 if (!ISSYMBOL (t)) return false;
327 return !is_object_in_scope (t) && is_typename (t) > 0 || t == bt_macro
328 || t == RESERVED__CLASS_;
331 /* A name can be the name of an object or the name of a typedef'd object */
332 recID lookup_object (Token t)
334 recID r;
335 typeID td;
337 if (t == RESERVED__CLASS_)
338 return objective.class;
339 if (r = lookup_struct (t))
340 return r;
341 if ((td = lookup_typedef (t)) != -1 && isstructure (td))
342 return base_of (td);
343 return 0;
345 /******************************************************************************
346 -- definitions of template functions outside the class
347 ******************************************************************************/
350 * The basetype could be class's name of an abstract class
351 * Z *Z.foo () { }
352 * something_undeclared Z.foo () { }
353 * search for the same name followed by a dot, before ( { ; ,
355 bool is_extern_templ_func (NormPtr *pp)
357 NormPtr s = *pp, p = *pp;
359 while (CODE [p] != '.' && CODE [p] != '(' && CODE [p] != ';'
360 && CODE [p] != ',' && CODE [p] != '{')
361 ++p;
363 if (CODE [p--] != '.')
364 return false;
366 if (!have_abstract (CODE [p]))
367 return false;
369 while (isdclflag (CODE [--s]));
370 *pp = p;
372 return is_template_function (pp, s + 1);
375 bool is_template_function (NormPtr *pp, NormPtr s)
377 NormPtr p = *pp;
378 Token n;
380 if (!have_abstract (n = CODE [p]))
381 return false;
383 if (CODE [p + 1] != '.') return false;
385 enter_abstract_external (n, s);
387 *pp = skip_declaration (p);
389 return true;
391 /******************************************************************************
392 -- global variables
393 ******************************************************************************/
395 static intnode *globalobjtree;
397 void enter_global_object (Token e, typeID t)
399 #ifdef DEBUG
400 if (debugflag.DCL_TRACE)
401 PRINTF ("DECLARING GLOBAL OBJECT ["COLS"%s"COLE"]\n", expand (e));
402 #endif
403 intnode *n = intfind (globalobjtree, e);
404 if (n && n->v.i != t)
405 parse_error_tok (e, "global object redefined");
406 union ival i = { .i = t };
407 intadd (&globalobjtree, e, i);
410 typeID lookup_global_object (Token e)
412 intnode *n = intfind (globalobjtree, e);
413 return n ? n->v.i : -1;
416 /******************************************************************************
417 local object scopes as found in declarations inside
418 compound statements.
419 ******************************************************************************/
421 typedef struct listobj_t {
422 struct listobj_t *next;
423 Token n, gn;
424 typeID t;
425 } listobj;
427 typedef struct autodtor_t {
428 struct autodtor_t *next;
429 Token o;
430 recID r;
431 bool ljmp;
432 } autodtor;
434 typedef struct codescope_t {
435 listobj *first;
436 autodtor *dtors;
438 // 1 for break, 2 for continue
439 int catchpoint;
441 // longbreak label name
442 Token lbrk, lcnt;
444 struct codescope_t *outer;
445 } codescope;
447 static codescope *inner;
449 void open_local_scope ()
451 codescope *c = (codescope*) malloc (sizeof * c);
452 c->first = 0;
453 c->dtors = 0;
454 c->catchpoint = 0;
455 c->lcnt = c->lbrk = 0;
456 c->outer = inner;
457 inner = c;
460 void *reopen_local_scope (void *n)
462 codescope *r = inner;
463 inner = (codescope*) n;
464 return r;
467 void restore_local_scope (void *n)
469 inner = (codescope*)n;
472 Token recent_obj ()
474 return inner->first->n;
477 void globalized_recent_obj (Token gn)
479 inner->first->gn = gn;
482 void add_catchpoint (int ct)
484 codescope *c = (codescope*) malloc (sizeof * c);
485 c->first = 0;
486 c->dtors = 0;
487 c->lcnt = c->lbrk = 0;
488 c->catchpoint = ct;
489 c->outer = inner;
490 inner = c;
493 void enter_local_obj (Token n, typeID t)
495 #ifdef DEBUG
496 if (debugflag.DCL_TRACE)
497 PRINTF ("DECLARING LOCAL OBJECT ["COLS"%s"COLE"]\n", expand (n));
498 #endif
499 listobj *l;
500 for (l = inner->first; l; l = l->next)
501 if (l->n == n)
502 parse_error_tok (n, "local object redefined");
503 l = (listobj*) malloc (sizeof * l);
504 l->n = n;
505 l->gn = 0;
506 l->t = t;
507 l->next = inner->first;
508 inner->first = l;
511 static void undo_auto_destruction (Token);
513 void undo_local_obj (Token n)
515 listobj *l, *p;
516 for (p = 0, l = inner->first; l; l = (p = l)->next)
517 if (l->n == n) break;
518 if (!p) inner->first = l->next;
519 else p->next = l->next;
520 free (l);
521 undo_auto_destruction (n);
524 typeID lookup_local_obj (Token n, Token *gn)
526 listobj *l;
527 codescope *c;
528 for (c = inner; c; c = c->outer)
529 for (l = c->first; l; l = l->next)
530 if (l->n == n) {
531 if (gn) *gn = l->gn;
532 /* Feature: structure by reference */
533 if (StructByRef && c->outer == 0 && isstructure (l->t))
534 return l->t + REFERENCE_BOOST;
535 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
536 return l->t;
538 return -1;
541 int close_local_scope ()
543 listobj *l, *ln;
544 for (l = inner->first; l; l = ln) {
545 ln = l->next;
546 free (l);
548 autodtor *al, *aln;
549 for (al = inner->dtors; al; al = aln) {
550 aln = al->next;
551 free (al);
553 codescope *f = inner;
554 inner = inner->outer;
555 free (f);
556 return !!inner;
559 void *active_scope ()
561 return inner;
564 void restore_scope (void *s)
566 while (inner != s) close_local_scope ();
569 void rmv_catchpoint (Token *lbrk, Token *lcnt)
571 if (!inner->catchpoint) parse_error_ll ("BUG. No catchpoint!");
572 if (inner->first) parse_error_ll ("BUG. Catchpoint has dcls");
573 codescope *f = inner;
574 *lbrk = f->lbrk;
575 *lcnt = f->lcnt;
576 inner = inner->outer;
577 free (f);
579 /**************************************************************
580 Automatic destruction of local objects
582 most of this is unused if EHUnwind is true
583 and the cleanup attribute is used instead.
584 ***************************************************************/
586 void add_auto_destruction (Token obj, recID rec, bool ljmp)
588 autodtor *na = (autodtor*) malloc (sizeof * na);
589 na->next = inner->dtors;
590 na->o = obj;
591 na->r = rec;
592 na->ljmp = ljmp;
593 inner->dtors = na;
596 static void undo_auto_destruction (Token n)
598 autodtor *a, *p;
599 for (p = 0, a = inner->dtors; a; a = (p = a)->next)
600 if (a->o == n) {
601 if (!p) inner->dtors = a->next;
602 else p->next = a->next;
603 if (a->ljmp) pop_unwind (0);
604 free (a);
605 return;
609 bool scope_has_dtors ()
611 return inner->dtors != 0;
614 /* member 'r' is normally a recID, but if a symbol, it's
615 the name of the custom dtor function. Useful for arrdtor */
616 #define DTOR_OF(x) ISSYMBOL(x) ? x : dtor_name (x)
618 void gen_auto_destruction (OUTSTREAM o, bool nothrow)
620 autodtor *a;
621 for (a = inner->dtors; a; a = a->next)
622 if (a->o == LEAVE_ESCOPE) leave_escope (o);
623 else {
624 if (a->ljmp && !nothrow) pop_unwind (o);
625 outprintf (o, DTOR_OF (a->r), '(', '&', a->o, ')', ';', -1);
629 bool break_has_dtors (int cp)
631 codescope *c;
632 for (c = inner; c && c->catchpoint < cp; c = c->outer)
633 if (c->dtors)
634 return true;
635 /* let C compiler complain if !c */
636 return false;
639 Token gen_break_destructors (OUTSTREAM o, int cp, int depth)
641 Token have [100] = { -1, };
642 autodtor *a;
643 codescope *c = inner, *d, *l = 0;
645 for (;;) {
646 continue_2:
647 for (; c && c->catchpoint < cp; c = c->outer)
648 for (a = c->dtors; a; a = a->next)
649 if (a->o == LEAVE_ESCOPE) leave_escope (o);
650 else {
651 if (a->ljmp) pop_unwind (o);
652 if (!intchr (have, a->o)) {
653 outprintf (o, DTOR_OF (a->r), '(', '&',
654 a->o, ')', ';', -1);
655 intcatc (have, a->o);
656 } else warning_tok ("outmost dtor not called due"
657 " to name conflict!!", a->o);
660 /* Handle: break n */
661 if (--depth && c)
662 for (d = c = c->outer; d; d = d->outer)
663 if (d->catchpoint >= cp) {
664 l = d;
665 goto continue_2;
667 break;
670 return !l ? 0 : cp == 2 ?
671 (l->lcnt ?: (l->lcnt = name_longcontinue ())) :
672 (l->lbrk ?: (l->lbrk = name_longbreak ()));
675 bool func_has_dtors ()
677 codescope *c;
678 for (c = inner; c; c = c->outer)
679 if (c->dtors)
680 return true;
681 return false;
684 void gen_all_destructors (OUTSTREAM o)
686 Token have [100] = { -1, };
687 codescope *c;
688 autodtor *a;
689 for (c = inner; c; c = c->outer)
690 for (a = c->dtors; a; a = a->next)
691 if (a->o == LEAVE_ESCOPE) leave_escope (o);
692 else {
693 if (a->ljmp) pop_unwind (o);
694 if (!intchr (have, a->o)) {
695 outprintf (o, DTOR_OF (a->r), '(', '&', a->o, ')', ';', -1);
696 intcatc (have, a->o);
697 } else warning_tok ("outmost dtor not called due to name"
698 " conflict!", a->o);