3 /******************************************************************************
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 /******************************************************************************
30 only interested for the existance of an enum tag
31 ******************************************************************************/
33 static intnode
*enumtree
;
36 enumID
enter_enum (Token e
)
39 if (n
= intfind (enumtree
, e
))
41 union ival i
= { .i
= en_inc
};
42 intadd (&enumtree
, e
, i
);
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 /******************************************************************************
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
)
79 if (debugflag
.TDEF_TRACE
)
80 PRINTF ("Enter typedef ["COLS
"%s"COLE
"]\n", expand (e
));
83 if ((n
= intfind (typedeftree
, e
))) {
85 parse_error_ll ("typedef redef");
88 union ival i
= { .i
= t
};
89 intadd (&typedeftree
, e
, i
);
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 /******************************************************************************
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
;
143 void enter_abstract (Token a
, Token
*par
, Token
*rpar
, NormPtr p
)
146 parse_error (p
, "Already have a class named that");
148 if (intfind (abstracttree
, a
))
149 parse_error_tok (a
, "abstract class redeclared");
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
));
160 A
->par
= intdup (par
);
161 A
->rpar
= intdup (rpar
);
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
;
197 for (i
= 0; i
< n
->nder
; i
++)
198 if (n
->der
[i
] == spec
)
203 bool have_abstract (Token a
)
205 return intfind (abstracttree
, a
) != 0;
208 int real_abstract_parents (Token a
, recID ip
[])
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
++)
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
;
242 for (i
= 0; i
< a
->nder
; i
++)
244 for (j
= 0; j
< a
->next
; j
++)
245 reparse_template_func (a
->name
, a
->der
[i
], a
->ext
[j
]);
250 if (n
->less
) r
|= do_for_class (n
->less
);
251 if (n
->more
) r
|= do_for_class (n
->more
);
255 bool specialize_abstracts ()
257 return abstracttree
? do_for_class (abstracttree
) : false;
259 /******************************************************************************
261 store/return the type string of a typeID
262 ******************************************************************************/
265 static int ntypes
, nalloc
;
267 typeID
enter_type (int *ts
)
270 for (i
= 0; i
< ntypes
; i
++)
271 if (!intcmp (types
[i
], ts
))
273 if (ntypes
== nalloc
)
274 types
= (int**) realloc (types
, (nalloc
+= 64) * sizeof (int*));
275 types
[ntypes
] = intdup (ts
);
279 int *open_typeID (typeID 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:
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
)
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
))
321 bool is_dcl_start (Token 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
)
337 if (t
== RESERVED__CLASS_
)
338 return objective
.class;
339 if (r
= lookup_struct (t
))
341 if ((td
= lookup_typedef (t
)) != -1 && isstructure (td
))
345 /******************************************************************************
346 -- definitions of template functions outside the class
347 ******************************************************************************/
350 * The basetype could be class's name of an abstract class
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
] != '{')
363 if (CODE
[p
--] != '.')
366 if (!have_abstract (CODE
[p
]))
369 while (isdclflag (CODE
[--s
]));
372 return is_template_function (pp
, s
+ 1);
375 bool is_template_function (NormPtr
*pp
, NormPtr s
)
380 if (!have_abstract (n
= CODE
[p
]))
383 if (CODE
[p
+ 1] != '.') return false;
385 enter_abstract_external (n
, s
);
387 *pp
= skip_declaration (p
);
391 /******************************************************************************
393 ******************************************************************************/
395 static intnode
*globalobjtree
;
397 void enter_global_object (Token e
, typeID t
)
400 if (debugflag
.DCL_TRACE
)
401 PRINTF ("DECLARING GLOBAL OBJECT ["COLS
"%s"COLE
"]\n", expand (e
));
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
419 ******************************************************************************/
421 typedef struct listobj_t
{
422 struct listobj_t
*next
;
427 typedef struct autodtor_t
{
428 struct autodtor_t
*next
;
434 typedef struct codescope_t
{
438 // 1 for break, 2 for continue
441 // longbreak label name
444 struct codescope_t
*outer
;
447 static codescope
*inner
;
449 void open_local_scope ()
451 codescope
*c
= (codescope
*) malloc (sizeof * c
);
455 c
->lcnt
= c
->lbrk
= 0;
460 void *reopen_local_scope (void *n
)
462 codescope
*r
= inner
;
463 inner
= (codescope
*) n
;
467 void restore_local_scope (void *n
)
469 inner
= (codescope
*)n
;
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
);
487 c
->lcnt
= c
->lbrk
= 0;
493 void enter_local_obj (Token n
, typeID t
)
496 if (debugflag
.DCL_TRACE
)
497 PRINTF ("DECLARING LOCAL OBJECT ["COLS
"%s"COLE
"]\n", expand (n
));
500 for (l
= inner
->first
; l
; l
= l
->next
)
502 parse_error_tok (n
, "local object redefined");
503 l
= (listobj
*) malloc (sizeof * l
);
507 l
->next
= inner
->first
;
511 static void undo_auto_destruction (Token
);
513 void undo_local_obj (Token n
)
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
;
521 undo_auto_destruction (n
);
524 typeID
lookup_local_obj (Token n
, Token
*gn
)
528 for (c
= inner
; c
; c
= c
->outer
)
529 for (l
= c
->first
; l
; l
= l
->next
)
532 /* Feature: structure by reference */
533 if (StructByRef
&& c
->outer
== 0 && isstructure (l
->t
))
534 return l
->t
+ REFERENCE_BOOST
;
535 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
541 int close_local_scope ()
544 for (l
= inner
->first
; l
; l
= ln
) {
549 for (al
= inner
->dtors
; al
; al
= aln
) {
553 codescope
*f
= inner
;
554 inner
= inner
->outer
;
559 void *active_scope ()
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
;
576 inner
= inner
->outer
;
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
;
596 static void undo_auto_destruction (Token n
)
599 for (p
= 0, a
= inner
->dtors
; a
; a
= (p
= a
)->next
)
601 if (!p
) inner
->dtors
= a
->next
;
602 else p
->next
= a
->next
;
603 if (a
->ljmp
) pop_unwind (0);
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
)
621 for (a
= inner
->dtors
; a
; a
= a
->next
)
622 if (a
->o
== LEAVE_ESCOPE
) leave_escope (o
);
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
)
632 for (c
= inner
; c
&& c
->catchpoint
< cp
; c
= c
->outer
)
635 /* let C compiler complain if !c */
639 Token
gen_break_destructors (OUTSTREAM o
, int cp
, int depth
)
641 Token have
[100] = { -1, };
643 codescope
*c
= inner
, *d
, *l
= 0;
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
);
651 if (a
->ljmp
) pop_unwind (o
);
652 if (!intchr (have
, a
->o
)) {
653 outprintf (o
, DTOR_OF (a
->r
), '(', '&',
655 intcatc (have
, a
->o
);
656 } else warning_tok ("outmost dtor not called due"
657 " to name conflict!!", a
->o
);
660 /* Handle: break n */
662 for (d
= c
= c
->outer
; d
; d
= d
->outer
)
663 if (d
->catchpoint
>= cp
) {
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 ()
678 for (c
= inner
; c
; c
= c
->outer
)
684 void gen_all_destructors (OUTSTREAM o
)
686 Token have
[100] = { -1, };
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
);
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"