1 /*****************************************************************************
3 Function namespaces. Overloading.
5 Overloading happens only when we have a second declaration of
6 the same name with different types in the same function space.
7 Then some things need to be renamed and are:
9 - prototype of function definition: rename_fdb
10 - name of auto functions to be reparsed: rename_hier
12 *****************************************************************************/
16 /**************************************************
17 Declarations, comparison of
18 prototypes, default arguments
20 **************************************************/
21 typeID
*promoted_arglist (typeID
*tt
)
26 for (j
= i
= 0; tt
[i
] != INTERNAL_ARGEND
; i
++)
27 tr
[j
++] = tt
[i
] == B_ELLIPSIS
? B_ELLIPSIS
:
28 isstructure (tt
[i
]) ?
29 ptrup (tt
[i
]) : bt_promotion (tt
[i
]);
34 typeID
*promoted_arglist_t (typeID t
)
36 return promoted_arglist (open_typeID (t
) + 2);
39 static char *mangle_type (char *p
, typeID t
, bool promo
)
41 if (is_reference (t
)) t
= ptrdown (dereference (t
));
42 int *ot
= open_typeID (t
);
44 for (i
= 1; ot
[i
] != -1; i
++)
45 if (ot
[i
] == '*' || ot
[i
] == '[') *p
++ = 'P';
46 else if (in2 (ot
[i
], '(', B_ELLIPSIS
)) {
47 *p
++ = ot
[i
] == '(' ? 'F' : 'E';
48 while (!in2 (ot
[i
], INTERNAL_ARGEND
, -1)) i
++;
49 if (ot
[i
] == -1) break;
50 } else parse_error (0, "BUG arglist");
52 char *tp
= expand (ISSYMBOL (ot
[0]) ? ot
[0] :
53 name_of_struct (ot
[0]));
54 /* Feature: structure by reference */
55 if (i
== 1) *p
++ = 'P';
56 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
58 while (*tp
) *p
++ = *tp
++;
59 } else if (ot
[1] == -1 && promo
) {
60 if (ot
[0] < B_FLOAT
) *p
++ = 'i';
61 else if (ot
[0] < B_VOID
) *p
++ = 'f';
62 else if (ot
[0] == B_VOID
) *p
++ = 'v';
63 } else switch (ot
[0]) {
64 #define uif if (!promo) *p++ = 'u';
66 case B_SCHAR
: *p
++ = 'c';
68 case B_SSINT
: *p
++ = 's';
70 case B_SINT
: *p
++ = 'i';
72 case B_SLONG
: *p
++ = 'l';
74 case B_SLLONG
: *p
++ = 'L';
75 ncase B_FLOAT
: *p
++ = 'f';
76 ncase B_DOUBLE
: *p
++ = 'F';
77 ncase B_LDOUBLE
: *p
++ = 'D';
83 char *nametype (char *ret
, typeID t
)
85 *mangle_type (ret
, t
, 0) = 0;
89 bool arglist_compare (typeID
*l1
, typeID
*l2
)
91 for (; *l1
!= -1 && *l2
!= -1; l1
++, l2
++)
93 if (isstructptr (*l1
) && isstructptr (*l2
)) {
94 recID r1
= aliasclass (base_of (*l1
));
95 recID r2
= aliasclass (base_of (*l2
));
96 if (r1
== r2
|| is_ancestor (r1
, r2
, 0, 0)
97 || is_ancestor (r2
, r1
, 0, 0)) continue;
104 char *type_string (char *r
, typeID t
)
108 int *ot
= open_typeID (t
) + 2;
110 for (argc
= 0; *ot
!= INTERNAL_ARGEND
; argc
++)
111 if (*ot
== B_ELLIPSIS
) *p
++ = 'E';
112 else p
= mangle_type (p
, *ot
++, 1);
113 sprintf (p
, "%i", argc
);
117 static void addflag (funcp
*p
, Token sp
)
119 Token
*n
= mallocint (intlen (p
->prototype
) + 2);
120 sintprintf (n
, sp
, ISTR (p
->prototype
), -1);
125 static funcp
*_declare_function (fspace
*SF
, Token e
, Token f
, typeID t
, Token
*proto
,
126 Token
*xargs
, int flagz
, Token section
)
130 typeID
*ovarglist
= promoted_arglist_t (t
);
133 bool used
= flagz
& FUNCP_VIRTUAL
;
136 if (!(S
= intfind (*SF
, e
))) {
138 p
= (funcp
*) malloc (sizeof *p
);
140 .next
= 0, .name
= f
, .type
= t
,
141 .prototype
= proto
? intdup (proto
) : 0,
142 .ovarglist
= ovarglist
, .dflt_args
= 0,
143 .xargs
= intdup (xargs
), .flagz
= flagz
, .used
= used
,
146 union ival u
= { .p
= p
};
153 for (rename
= true, un
= p
->name
, w
= p
; w
; w
= w
->next
)
160 /*** second time ***/
161 // overload existing functions declared previously
162 for (w
= p
; w
; w
= w
->next
)
163 if (arglist_compare (ovarglist
, w
->ovarglist
)) {
164 // same function prototype again. no overload
166 {fprintf (stderr
, "BAD FUNCTION[%s]\n", expand (e
));
167 parse_error_ll ("overloading match, type mis-match");
169 if (flagz
& FUNCP_STATIC
&& !intchr (w
->prototype
, RESERVED_static
))
170 addflag (w
, RESERVED_static
);
171 if (flagz
& FUNCP_INLINE
&& !intchr (w
->prototype
, RESERVED_inline
))
172 addflag (w
, RESERVED_inline
);
176 Token nf1
= name_overload_fun (f
, type_string (st
, p
->type
));
177 rename_fdb (p
->name
, nf1
);
178 rename_hier (p
->name
, nf1
);
179 for (w
= p
; w
; p
= w
, w
= w
->next
) {
181 intsubst (w
->prototype
, w
->name
, nf1
);
185 Token nf2
= name_overload_fun (f
, type_string (st
, t
));
186 if (nf2
== nf1
) parse_error_tok (nf1
, "Different functions, same overloaded name!");
188 intsubst (proto
, f
, nf2
);
189 p
->next
= (funcp
*) malloc (sizeof *p
);
192 .next
= 0, .name
= nf2
, .type
= t
,
193 .prototype
= proto
? intdup (proto
) : 0,
194 .ovarglist
= ovarglist
, .dflt_args
= 0,
195 .xargs
= intdup (xargs
), .flagz
= flagz
, .used
= used
201 for (w
= p
; w
; p
= w
, w
= w
->next
)
202 if (arglist_compare (ovarglist
, w
->ovarglist
)) {
204 {fprintf (stderr
, "BAD FUNCTION[%s]\n", expand (e
));
205 parse_error_ll ("overload match, type mismatch");
207 if (flagz
& FUNCP_STATIC
&& !intchr (w
->prototype
, RESERVED_static
))
208 addflag (w
, RESERVED_static
);
209 if (flagz
& FUNCP_INLINE
&& !intchr (w
->prototype
, RESERVED_inline
))
210 addflag (w
, RESERVED_inline
);
215 Token nf
= name_overload_fun (f
, type_string (st
, t
));
216 for (w
= p
; w
; p
= w
, w
= w
->next
)
218 parse_error_tok (nf
, "Error: overloaded functions boil down to same name.");
220 intsubst (proto
, f
, nf
);
221 p
->next
= (funcp
*) malloc (sizeof *p
);
224 .next
= 0, .name
= nf
, .type
= t
,
225 .prototype
= proto
? intdup (proto
) : 0,
226 .ovarglist
= ovarglist
, .dflt_args
= 0,
227 .xargs
= intdup (xargs
), .flagz
= flagz
, .used
= used
,
233 static typeID
rmv_last_arg (typeID ft
)
235 int *oo
= open_typeID (ft
);
236 int *o
= allocaint (intlen (oo
) + 2);
239 for (i
= 0; o
[i
] != INTERNAL_ARGEND
; i
++);
240 while ((o
[i
-1] = o
[i
]) != -1) i
++;
241 return enter_type (o
);
244 funcp
*xdeclare_function (fspace
*S
, Token e
, Token f
, typeID t
, Token
*proto
,
245 Token
*xargs
, int flagz
, Token
**dflt
, Token section
)
248 if (debugflag
.DCL_TRACE
) {
249 PRINTF ("DECLARING FUNCTION ["COLS
"%s"COLE
", %s]\n", expand (f
), expand (e
));
250 PRINTF ("dflt=%p OF TYPE: ", dflt
);
252 PRINTF ("flagz=%i\n", flagz
);
258 if (Streams_Closed
) proto
= 0;
260 f
= (p
= _declare_function (S
, e
, f
, t
, proto
, xargs
, flagz
, section
))->name
;
263 for (dargc
= 0; dflt
[dargc
]; dargc
++);
265 proto
= p
->prototype
;
266 for (i
= 0, --dargc
; i
<= dargc
; i
++) {
267 t
= rmv_last_arg (t
);
268 p
= p
->next
= (funcp
*) malloc (sizeof *p
);
270 .next
= 0, .name
= f
, .type
= t
,
271 .prototype
= proto
, .ovarglist
= promoted_arglist_t (t
),
272 .dflt_args
= &dflt
[dargc
- i
], .section
= section
,
273 .xargs
= intdup (xargs
), .flagz
= flagz
, .used
= flagz
& FUNCP_VIRTUAL
280 void xmark_section_linkonce (fspace S
, Token fn
, Token ofn
)
282 funcp
*p
= (funcp
*) intfind (S
, fn
)->v
.p
;
283 while (p
->name
!= ofn
)
285 p
->flagz
|= FUNCP_LINKONCE
;
289 void xmark_nothrow (fspace S
, Token fn
, Token ofn
)
291 intnode
*n
= intfind (S
, fn
);
293 funcp
*p
= (funcp
*) n
->v
.p
;
294 while (p
->name
!= ofn
)
296 p
->flagz
|= FUNCP_NOTHROW
;
299 /* function is used by alias so if static inline, mark __attribute__ ((used)) */
300 int xmark_function_USED (fspace S
, Token ofn
)
303 for (p
= (funcp
*) S
->v
.p
; p
; p
= p
->next
)
304 if (p
->name
== ofn
) {
305 p
->flagz
|= FUNCP_USED
;
308 if (S
->less
&& xmark_function_USED (S
->less
, ofn
))
310 return S
->more
? xmark_function_USED (S
->more
, ofn
) : 0;
313 /* lookup a declaration. exact arglist match */
314 funcp
*xlookup_function_dcl (fspace S
, Token f
, typeID argv
[])
320 for (p
= (funcp
*) S
->v
.p
; p
; p
= p
->next
)
321 if (arglist_compare (p
->ovarglist
, argv
))
326 /**************************************************
327 Lookups in function spaces
328 **************************************************/
332 typeID
lookup_function_symbol (Token e
)
334 intnode
*n
= intfind (Global
, e
);
336 funcp
*p
= (funcp
*) n
->v
.p
;
338 expr_errort ("function is overloaded. can't get address by name", e
);
343 bool have_function (fspace S
, Token f
)
345 return intfind (S
, f
) != 0;
348 Token
xlookup_function_uname (fspace S
, Token f
)
350 intnode
*n
= intfind (S
, f
);
352 funcp
*p
= (funcp
*) n
->v
.p
;
354 parse_error_tok (f
, "function is overloaded. can't get alias by name");
360 -1. lists, for one, have different argc
361 0. call list doesn't match
362 1. match after promotion
365 The second list is the call argument list while the first
366 the list of the function prototype. It matters
368 static int callist_compare (typeID
*l1
, typeID
*l2
)
370 if (*l1
== typeID_void
&& *l2
== -1)
373 for (; *l2
!= -1; l1
++, l2
++)
375 if (in2 (B_ELLIPSIS
, *l1
, *l2
) || typeID_elliptic (*l2
)
376 || (*l1
>= 0 && typeID_elliptic (*l1
)))
378 if (*l1
< 0) return -1;
379 /* Feature: Hierarchy matches types */
380 if (isstructptr (*l1
) && isstructptr (*l2
)) {
381 recID r1
= aliasclass (dbase_of (*l1
));
382 recID r2
= aliasclass (base_of (*l2
));
383 if (r1
== r2
) continue;
384 if (is_ancestor (r2
, r1
, 0, 0))
387 /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
388 if (ispointer (*l1
) && ispointer (*l2
))
389 if (*l1
== typeID_voidP
|| *l2
== typeID_voidP
)
391 if (is_reference (*l1
) && bt_promotion (ptrdown (dereference (*l1
))) == *l2
)
393 if (*l2
== typeID_int
&& *l1
== typeID_float
)
395 if (*l1
== typeID_int
&& *l2
== typeID_float
)
397 /* XXX: Comparing '0' with pointer is ok.... */
402 return *l1
== *l2
|| *l1
== B_ELLIPSIS
|| typeID_elliptic (*l1
) ? ret
: -1;
405 /* the return value means:
406 -1: name does not even exist
408 1: matches in number of arguments
409 2: -candidate- conversions match
412 int xlookup_function (fspace S
, Token e
, typeID argv
[], flookup
*ret
)
415 funcp
*o
, *match
= 0;
416 int mt
= -1, error
= 0, rez
;
420 typeID
*ovarglist
= promoted_arglist (argv
);
422 for (; o
; o
= o
->next
) {
423 rez
= callist_compare (o
->ovarglist
, ovarglist
);
424 if (rez
== -1) continue;
429 } else if (mt
== rez
) {
434 if (!ret
) return mt
+ 1;
436 if (error
) expr_errort ("AMBIGOUS overload call", e
);
439 if (mt
== -1) return 0;
441 ret
->oname
= match
->name
;
442 ret
->t
= match
->type
;
443 if (ret
->dflt_args
= match
->dflt_args
) {
444 for (o
= (funcp
*) S
->v
.p
; o
->name
!= match
->name
; o
= o
->next
);
447 ret
->xargs
= match
->xargs
;
448 ret
->flagz
= match
->flagz
;
449 ret
->prototype
= match
->prototype
;
453 /**************************************************
455 Export the prototypes used
457 **************************************************/
459 OUTSTREAM
printproto (OUTSTREAM O
, Token proto
[], Token fnm
, bool palias
)
464 for (; proto
[i
] != -1; i
++) {
465 if (proto
[i
] == fnm
) {
466 output_itoken (O
, RESERVED_attr_stdcall
);
469 output_itoken (O
, proto
[i
]);
471 outprintf (O
, ISTR (proto
+ i
), -1);
473 for (i
= 0; proto
[i
] != -1; i
++) {
474 if (proto
[i
] == RESERVED___attribute__
)
476 output_itoken (O
, proto
[i
]);
482 OUTSTREAM
printproto_si (OUTSTREAM O
, Token proto
[], Token fnm
, bool palias
)
484 if (!intchr (proto
, RESERVED_static
))
485 output_itoken (O
, RESERVED_static
);
486 if (!intchr (proto
, RESERVED_inline
))
487 output_itoken (O
, RESERVED_inline
);
488 return printproto (O
, proto
, fnm
, palias
);
491 void export_fspace (fspace F
)
495 for (p
= (funcp
*) F
->v
.p
; p
; p
= p
->next
)
496 if (p
->used
&& !p
->dflt_args
&& p
->prototype
497 && !(p
->flagz
& (/*FUNCP_PURE|*/FUNCP_AUTO
))) {
498 outprintf (FPROTOS
, ISTR (p
->prototype
), -1);
499 if (p
->flagz
& FUNCP_LINKONCE
&& !(p
->flagz
& FUNCP_STATIC
))
500 output_itoken (FPROTOS
, linkonce_text (p
->name
));
502 outprintf (FPROTOS
, RESERVED___attribute__
, '(', '(',
503 RESERVED___section__
, '(', p
->section
, ')', ')', ')',-1);
504 output_itoken (FPROTOS
, ';');
507 if (F
->less
) export_fspace (F
->less
);
508 if (F
->more
) export_fspace (F
->more
);
511 void export_fspace_lwc (fspace F
)
515 for (p
= (funcp
*) F
->v
.p
; p
; p
= p
->next
)
516 if (p
->used
&& !p
->dflt_args
&& p
->prototype
517 && !(p
->flagz
& (/*FUNCP_PURE|*/FUNCP_AUTO
))) {
518 printproto (FPROTOS
, p
->prototype
, p
->name
, 1);
519 if (p
->flagz
& FUNCP_LINKONCE
&& !(p
->flagz
& FUNCP_STATIC
))
520 output_itoken (FPROTOS
, linkonce_text (p
->name
));
522 outprintf (FPROTOS
, RESERVED___attribute__
, '(', '(',
523 RESERVED___section__
, '(', p
->section
, ')', ')', ')',-1);
524 if (p
->flagz
& FUNCP_USED
)
525 outprintf (FPROTOS
, RESERVED___attribute__
, '(', '(', RESERVED_used
, ')', ')', -1);
526 output_itoken (FPROTOS
, ';');
529 if (F
->less
) export_fspace_lwc (F
->less
);
530 if (F
->more
) export_fspace_lwc (F
->more
);