1 | /* Generate information regarding function declarations and definitions based |
2 | on information stored in GCC's tree structure. This code implements the |
3 | -aux-info option. |
4 | Copyright (C) 1989-2023 Free Software Foundation, Inc. |
5 | Contributed by Ron Guilmette (rfg@segfault.us.com). |
6 | |
7 | This file is part of GCC. |
8 | |
9 | GCC is free software; you can redistribute it and/or modify it under |
10 | the terms of the GNU General Public License as published by the Free |
11 | Software Foundation; either version 3, or (at your option) any later |
12 | version. |
13 | |
14 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
15 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
16 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
17 | for more details. |
18 | |
19 | You should have received a copy of the GNU General Public License |
20 | along with GCC; see the file COPYING3. If not see |
21 | <http://www.gnu.org/licenses/>. */ |
22 | |
23 | #include "config.h" |
24 | #include "system.h" |
25 | #include "coretypes.h" |
26 | #include "tm.h" |
27 | #include "c-tree.h" |
28 | |
29 | enum formals_style { |
30 | ansi, |
31 | k_and_r_names, |
32 | k_and_r_decls |
33 | }; |
34 | |
35 | |
36 | static const char *data_type; |
37 | |
38 | static char *affix_data_type (const char *) ATTRIBUTE_MALLOC; |
39 | static const char *gen_formal_list_for_type (tree, formals_style); |
40 | static const char *gen_formal_list_for_func_def (tree, formals_style); |
41 | static const char *gen_type (const char *, tree, formals_style); |
42 | static const char *gen_decl (tree, int, formals_style); |
43 | |
44 | /* Given a string representing an entire type or an entire declaration |
45 | which only lacks the actual "data-type" specifier (at its left end), |
46 | affix the data-type specifier to the left end of the given type |
47 | specification or object declaration. |
48 | |
49 | Because of C language weirdness, the data-type specifier (which normally |
50 | goes in at the very left end) may have to be slipped in just to the |
51 | right of any leading "const" or "volatile" qualifiers (there may be more |
52 | than one). Actually this may not be strictly necessary because it seems |
53 | that GCC (at least) accepts `<data-type> const foo;' and treats it the |
54 | same as `const <data-type> foo;' but people are accustomed to seeing |
55 | `const char *foo;' and *not* `char const *foo;' so we try to create types |
56 | that look as expected. */ |
57 | |
58 | static char * |
59 | affix_data_type (const char *param) |
60 | { |
61 | char *const type_or_decl = ASTRDUP (param); |
62 | char *p = type_or_decl; |
63 | char *qualifiers_then_data_type; |
64 | char saved; |
65 | |
66 | /* Skip as many leading const's or volatile's as there are. */ |
67 | |
68 | for (;;) |
69 | { |
70 | if (startswith (str: p, prefix: "volatile " )) |
71 | { |
72 | p += 9; |
73 | continue; |
74 | } |
75 | if (startswith (str: p, prefix: "const " )) |
76 | { |
77 | p += 6; |
78 | continue; |
79 | } |
80 | break; |
81 | } |
82 | |
83 | /* p now points to the place where we can insert the data type. We have to |
84 | add a blank after the data-type of course. */ |
85 | |
86 | if (p == type_or_decl) |
87 | return concat (data_type, " " , type_or_decl, NULL); |
88 | |
89 | saved = *p; |
90 | *p = '\0'; |
91 | qualifiers_then_data_type = concat (type_or_decl, data_type, NULL); |
92 | *p = saved; |
93 | return reconcat (qualifiers_then_data_type, |
94 | qualifiers_then_data_type, " " , p, NULL); |
95 | } |
96 | |
97 | /* Given a tree node which represents some "function type", generate the |
98 | source code version of a formal parameter list (of some given style) for |
99 | this function type. Return the whole formal parameter list (including |
100 | a pair of surrounding parens) as a string. Note that if the style |
101 | we are currently aiming for is non-ansi, then we just return a pair |
102 | of empty parens here. */ |
103 | |
104 | static const char * |
105 | gen_formal_list_for_type (tree fntype, formals_style style) |
106 | { |
107 | const char *formal_list = "" ; |
108 | tree formal_type; |
109 | |
110 | if (style != ansi) |
111 | return "()" ; |
112 | |
113 | formal_type = TYPE_ARG_TYPES (fntype); |
114 | while (formal_type && TREE_VALUE (formal_type) != void_type_node) |
115 | { |
116 | const char *this_type; |
117 | |
118 | if (*formal_list) |
119 | formal_list = concat (formal_list, ", " , NULL); |
120 | |
121 | this_type = gen_type ("" , TREE_VALUE (formal_type), ansi); |
122 | formal_list |
123 | = ((strlen (s: this_type)) |
124 | ? concat (formal_list, affix_data_type (param: this_type), NULL) |
125 | : concat (formal_list, data_type, NULL)); |
126 | |
127 | formal_type = TREE_CHAIN (formal_type); |
128 | } |
129 | |
130 | /* If we got to here, then we are trying to generate an ANSI style formal |
131 | parameters list. |
132 | |
133 | New style prototyped ANSI formal parameter lists should in theory always |
134 | contain some stuff between the opening and closing parens, even if it is |
135 | only "void". |
136 | |
137 | The brutal truth though is that there is lots of old K&R code out there |
138 | which contains declarations of "pointer-to-function" parameters and |
139 | these almost never have fully specified formal parameter lists associated |
140 | with them. That is, the pointer-to-function parameters are declared |
141 | with just empty parameter lists. |
142 | |
143 | In cases such as these, protoize should really insert *something* into |
144 | the vacant parameter lists, but what? It has no basis on which to insert |
145 | anything in particular. |
146 | |
147 | Here, we make life easy for protoize by trying to distinguish between |
148 | K&R empty parameter lists and new-style prototyped parameter lists |
149 | that actually contain "void". In the latter case we (obviously) want |
150 | to output the "void" verbatim, and that what we do. In the former case, |
151 | we do our best to give protoize something nice to insert. |
152 | |
153 | This "something nice" should be something that is still valid (when |
154 | re-compiled) but something that can clearly indicate to the user that |
155 | more typing information (for the parameter list) should be added (by |
156 | hand) at some convenient moment. |
157 | |
158 | The string chosen here is a comment with question marks in it. */ |
159 | |
160 | if (!*formal_list) |
161 | { |
162 | if (prototype_p (fntype)) |
163 | /* assert (TREE_VALUE (TYPE_ARG_TYPES (fntype)) == void_type_node); */ |
164 | formal_list = "void" ; |
165 | else |
166 | formal_list = "/* ??? */" ; |
167 | } |
168 | else |
169 | { |
170 | /* If there were at least some parameters, and if the formals-types-list |
171 | petered out to a NULL (i.e. without being terminated by a |
172 | void_type_node) then we need to tack on an ellipsis. */ |
173 | if (!formal_type) |
174 | formal_list = concat (formal_list, ", ..." , NULL); |
175 | } |
176 | |
177 | return concat (" (" , formal_list, ")" , NULL); |
178 | } |
179 | |
180 | /* Generate a parameter list for a function definition (in some given style). |
181 | |
182 | Note that this routine has to be separate (and different) from the code that |
183 | generates the prototype parameter lists for function declarations, because |
184 | in the case of a function declaration, all we have to go on is a tree node |
185 | representing the function's own "function type". This can tell us the types |
186 | of all of the formal parameters for the function, but it cannot tell us the |
187 | actual *names* of each of the formal parameters. We need to output those |
188 | parameter names for each function definition. |
189 | |
190 | This routine gets a pointer to a tree node which represents the actual |
191 | declaration of the given function, and this DECL node has a list of formal |
192 | parameter (variable) declarations attached to it. These formal parameter |
193 | (variable) declaration nodes give us the actual names of the formal |
194 | parameters for the given function definition. |
195 | |
196 | This routine returns a string which is the source form for the entire |
197 | function formal parameter list. */ |
198 | |
199 | static const char * |
200 | gen_formal_list_for_func_def (tree fndecl, formals_style style) |
201 | { |
202 | const char *formal_list = "" ; |
203 | tree formal_decl; |
204 | |
205 | formal_decl = DECL_ARGUMENTS (fndecl); |
206 | while (formal_decl) |
207 | { |
208 | const char *this_formal; |
209 | |
210 | if (*formal_list && ((style == ansi) || (style == k_and_r_names))) |
211 | formal_list = concat (formal_list, ", " , NULL); |
212 | this_formal = gen_decl (formal_decl, 0, style); |
213 | if (style == k_and_r_decls) |
214 | formal_list = concat (formal_list, this_formal, "; " , NULL); |
215 | else |
216 | formal_list = concat (formal_list, this_formal, NULL); |
217 | formal_decl = TREE_CHAIN (formal_decl); |
218 | } |
219 | if (style == ansi) |
220 | { |
221 | if (!DECL_ARGUMENTS (fndecl)) |
222 | formal_list = concat (formal_list, "void" , NULL); |
223 | if (stdarg_p (TREE_TYPE (fndecl))) |
224 | formal_list = concat (formal_list, ", ..." , NULL); |
225 | } |
226 | if ((style == ansi) || (style == k_and_r_names)) |
227 | formal_list = concat (" (" , formal_list, ")" , NULL); |
228 | return formal_list; |
229 | } |
230 | |
231 | /* Generate a string which is the source code form for a given type (t). This |
232 | routine is ugly and complex because the C syntax for declarations is ugly |
233 | and complex. This routine is straightforward so long as *no* pointer types, |
234 | array types, or function types are involved. |
235 | |
236 | In the simple cases, this routine will return the (string) value which was |
237 | passed in as the "ret_val" argument. Usually, this starts out either as an |
238 | empty string, or as the name of the declared item (i.e. the formal function |
239 | parameter variable). |
240 | |
241 | This routine will also return with the global variable "data_type" set to |
242 | some string value which is the "basic" data-type of the given complete type. |
243 | This "data_type" string can be concatenated onto the front of the returned |
244 | string after this routine returns to its caller. |
245 | |
246 | In complicated cases involving pointer types, array types, or function |
247 | types, the C declaration syntax requires an "inside out" approach, i.e. if |
248 | you have a type which is a "pointer-to-function" type, you need to handle |
249 | the "pointer" part first, but it also has to be "innermost" (relative to |
250 | the declaration stuff for the "function" type). Thus, is this case, you |
251 | must prepend a "(*" and append a ")" to the name of the item (i.e. formal |
252 | variable). Then you must append and prepend the other info for the |
253 | "function type" part of the overall type. |
254 | |
255 | To handle the "innermost precedence" rules of complicated C declarators, we |
256 | do the following (in this routine). The input parameter called "ret_val" |
257 | is treated as a "seed". Each time gen_type is called (perhaps recursively) |
258 | some additional strings may be appended or prepended (or both) to the "seed" |
259 | string. If yet another (lower) level of the GCC tree exists for the given |
260 | type (as in the case of a pointer type, an array type, or a function type) |
261 | then the (wrapped) seed is passed to a (recursive) invocation of gen_type() |
262 | this recursive invocation may again "wrap" the (new) seed with yet more |
263 | declarator stuff, by appending, prepending (or both). By the time the |
264 | recursion bottoms out, the "seed value" at that point will have a value |
265 | which is (almost) the complete source version of the declarator (except |
266 | for the data_type info). Thus, this deepest "seed" value is simply passed |
267 | back up through all of the recursive calls until it is given (as the return |
268 | value) to the initial caller of the gen_type() routine. All that remains |
269 | to do at this point is for the initial caller to prepend the "data_type" |
270 | string onto the returned "seed". */ |
271 | |
272 | static const char * |
273 | gen_type (const char *ret_val, tree t, formals_style style) |
274 | { |
275 | tree chain_p; |
276 | |
277 | /* If there is a typedef name for this type, use it. */ |
278 | if (TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) |
279 | data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t))); |
280 | else |
281 | { |
282 | switch (TREE_CODE (t)) |
283 | { |
284 | case POINTER_TYPE: |
285 | if (TYPE_ATOMIC (t)) |
286 | ret_val = concat ("_Atomic " , ret_val, NULL); |
287 | if (TYPE_READONLY (t)) |
288 | ret_val = concat ("const " , ret_val, NULL); |
289 | if (TYPE_VOLATILE (t)) |
290 | ret_val = concat ("volatile " , ret_val, NULL); |
291 | |
292 | ret_val = concat ("*" , ret_val, NULL); |
293 | |
294 | if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) |
295 | ret_val = concat ("(" , ret_val, ")" , NULL); |
296 | |
297 | ret_val = gen_type (ret_val, TREE_TYPE (t), style); |
298 | |
299 | return ret_val; |
300 | |
301 | case ARRAY_TYPE: |
302 | if (!COMPLETE_TYPE_P (t) || TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST) |
303 | ret_val = gen_type (ret_val: concat (ret_val, "[]" , NULL), |
304 | TREE_TYPE (t), style); |
305 | else if (int_size_in_bytes (t) == 0) |
306 | ret_val = gen_type (ret_val: concat (ret_val, "[0]" , NULL), |
307 | TREE_TYPE (t), style); |
308 | else |
309 | { |
310 | char buff[23]; |
311 | sprintf (s: buff, format: "[" HOST_WIDE_INT_PRINT_DEC"]" , |
312 | int_size_in_bytes (t) |
313 | / int_size_in_bytes (TREE_TYPE (t))); |
314 | ret_val = gen_type (ret_val: concat (ret_val, buff, NULL), |
315 | TREE_TYPE (t), style); |
316 | } |
317 | break; |
318 | |
319 | case FUNCTION_TYPE: |
320 | ret_val = gen_type (ret_val: concat (ret_val, |
321 | gen_formal_list_for_type (fntype: t, style), |
322 | NULL), |
323 | TREE_TYPE (t), style); |
324 | break; |
325 | |
326 | case IDENTIFIER_NODE: |
327 | data_type = IDENTIFIER_POINTER (t); |
328 | break; |
329 | |
330 | /* The following three cases are complicated by the fact that a |
331 | user may do something really stupid, like creating a brand new |
332 | "anonymous" type specification in a formal argument list (or as |
333 | part of a function return type specification). For example: |
334 | |
335 | int f (enum { red, green, blue } color); |
336 | |
337 | In such cases, we have no name that we can put into the prototype |
338 | to represent the (anonymous) type. Thus, we have to generate the |
339 | whole darn type specification. Yuck! */ |
340 | |
341 | case RECORD_TYPE: |
342 | if (TYPE_NAME (t)) |
343 | data_type = IDENTIFIER_POINTER (TYPE_NAME (t)); |
344 | else |
345 | { |
346 | data_type = "" ; |
347 | chain_p = TYPE_FIELDS (t); |
348 | while (chain_p) |
349 | { |
350 | data_type = concat (data_type, gen_decl (chain_p, 0, ansi), |
351 | NULL); |
352 | chain_p = TREE_CHAIN (chain_p); |
353 | data_type = concat (data_type, "; " , NULL); |
354 | } |
355 | data_type = concat ("{ " , data_type, "}" , NULL); |
356 | } |
357 | data_type = concat ("struct " , data_type, NULL); |
358 | break; |
359 | |
360 | case UNION_TYPE: |
361 | if (TYPE_NAME (t)) |
362 | data_type = IDENTIFIER_POINTER (TYPE_NAME (t)); |
363 | else |
364 | { |
365 | data_type = "" ; |
366 | chain_p = TYPE_FIELDS (t); |
367 | while (chain_p) |
368 | { |
369 | data_type = concat (data_type, gen_decl (chain_p, 0, ansi), |
370 | NULL); |
371 | chain_p = TREE_CHAIN (chain_p); |
372 | data_type = concat (data_type, "; " , NULL); |
373 | } |
374 | data_type = concat ("{ " , data_type, "}" , NULL); |
375 | } |
376 | data_type = concat ("union " , data_type, NULL); |
377 | break; |
378 | |
379 | case ENUMERAL_TYPE: |
380 | if (TYPE_NAME (t)) |
381 | data_type = IDENTIFIER_POINTER (TYPE_NAME (t)); |
382 | else |
383 | { |
384 | data_type = "" ; |
385 | chain_p = TYPE_VALUES (t); |
386 | while (chain_p) |
387 | { |
388 | data_type = concat (data_type, |
389 | IDENTIFIER_POINTER (TREE_PURPOSE (chain_p)), NULL); |
390 | chain_p = TREE_CHAIN (chain_p); |
391 | if (chain_p) |
392 | data_type = concat (data_type, ", " , NULL); |
393 | } |
394 | data_type = concat ("{ " , data_type, " }" , NULL); |
395 | } |
396 | data_type = concat ("enum " , data_type, NULL); |
397 | break; |
398 | |
399 | case TYPE_DECL: |
400 | data_type = IDENTIFIER_POINTER (DECL_NAME (t)); |
401 | break; |
402 | |
403 | case INTEGER_TYPE: |
404 | case FIXED_POINT_TYPE: |
405 | data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t))); |
406 | /* Normally, `unsigned' is part of the deal. Not so if it comes |
407 | with a type qualifier. */ |
408 | if (TYPE_UNSIGNED (t) && TYPE_QUALS (t)) |
409 | data_type = concat ("unsigned " , data_type, NULL); |
410 | break; |
411 | |
412 | case BITINT_TYPE: |
413 | { |
414 | char buf[sizeof ("2147483647" )]; |
415 | sprintf (s: buf, format: "%d" , TYPE_PRECISION (t)); |
416 | if (TYPE_UNSIGNED (t)) |
417 | data_type = concat ("unsigned _BitInt(" , buf, ")" , NULL); |
418 | else |
419 | data_type = concat ("_BitInt(" , buf, ")" , NULL); |
420 | break; |
421 | } |
422 | |
423 | case OPAQUE_TYPE: |
424 | case REAL_TYPE: |
425 | data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t))); |
426 | break; |
427 | |
428 | case VOID_TYPE: |
429 | data_type = "void" ; |
430 | break; |
431 | |
432 | case ERROR_MARK: |
433 | data_type = "[ERROR]" ; |
434 | break; |
435 | |
436 | default: |
437 | gcc_unreachable (); |
438 | } |
439 | } |
440 | if (TYPE_ATOMIC (t)) |
441 | ret_val = concat ("_Atomic " , ret_val, NULL); |
442 | if (TYPE_READONLY (t)) |
443 | ret_val = concat ("const " , ret_val, NULL); |
444 | if (TYPE_VOLATILE (t)) |
445 | ret_val = concat ("volatile " , ret_val, NULL); |
446 | if (TYPE_RESTRICT (t)) |
447 | ret_val = concat ("restrict " , ret_val, NULL); |
448 | return ret_val; |
449 | } |
450 | |
451 | /* Generate a string (source) representation of an entire entity declaration |
452 | (using some particular style for function types). |
453 | |
454 | The given entity may be either a variable or a function. |
455 | |
456 | If the "is_func_definition" parameter is nonzero, assume that the thing |
457 | we are generating a declaration for is a FUNCTION_DECL node which is |
458 | associated with a function definition. In this case, we can assume that |
459 | an attached list of DECL nodes for function formal arguments is present. */ |
460 | |
461 | static const char * |
462 | gen_decl (tree decl, int is_func_definition, formals_style style) |
463 | { |
464 | const char *ret_val; |
465 | |
466 | if (DECL_NAME (decl)) |
467 | ret_val = IDENTIFIER_POINTER (DECL_NAME (decl)); |
468 | else |
469 | ret_val = "" ; |
470 | |
471 | /* If we are just generating a list of names of formal parameters, we can |
472 | simply return the formal parameter name (with no typing information |
473 | attached to it) now. */ |
474 | |
475 | if (style == k_and_r_names) |
476 | return ret_val; |
477 | |
478 | /* Note that for the declaration of some entity (either a function or a |
479 | data object, like for instance a parameter) if the entity itself was |
480 | declared as either const or volatile, then const and volatile properties |
481 | are associated with just the declaration of the entity, and *not* with |
482 | the `type' of the entity. Thus, for such declared entities, we have to |
483 | generate the qualifiers here. */ |
484 | |
485 | if (TREE_THIS_VOLATILE (decl)) |
486 | ret_val = concat ("volatile " , ret_val, NULL); |
487 | if (TREE_READONLY (decl)) |
488 | ret_val = concat ("const " , ret_val, NULL); |
489 | |
490 | data_type = "" ; |
491 | |
492 | /* For FUNCTION_DECL nodes, there are two possible cases here. First, if |
493 | this FUNCTION_DECL node was generated from a function "definition", then |
494 | we will have a list of DECL_NODE's, one for each of the function's formal |
495 | parameters. In this case, we can print out not only the types of each |
496 | formal, but also each formal's name. In the second case, this |
497 | FUNCTION_DECL node came from an actual function declaration (and *not* |
498 | a definition). In this case, we do nothing here because the formal |
499 | argument type-list will be output later, when the "type" of the function |
500 | is added to the string we are building. Note that the ANSI-style formal |
501 | parameter list is considered to be a (suffix) part of the "type" of the |
502 | function. */ |
503 | |
504 | if (TREE_CODE (decl) == FUNCTION_DECL && is_func_definition) |
505 | { |
506 | ret_val = concat (ret_val, gen_formal_list_for_func_def (fndecl: decl, style: ansi), |
507 | NULL); |
508 | |
509 | /* Since we have already added in the formals list stuff, here we don't |
510 | add the whole "type" of the function we are considering (which |
511 | would include its parameter-list info), rather, we only add in |
512 | the "type" of the "type" of the function, which is really just |
513 | the return-type of the function (and does not include the parameter |
514 | list info). */ |
515 | |
516 | ret_val = gen_type (ret_val, TREE_TYPE (TREE_TYPE (decl)), style); |
517 | } |
518 | else |
519 | ret_val = gen_type (ret_val, TREE_TYPE (decl), style); |
520 | |
521 | ret_val = affix_data_type (param: ret_val); |
522 | |
523 | if (TREE_CODE (decl) != FUNCTION_DECL && C_DECL_REGISTER (decl)) |
524 | ret_val = concat ("register " , ret_val, NULL); |
525 | if (TREE_PUBLIC (decl)) |
526 | ret_val = concat ("extern " , ret_val, NULL); |
527 | if (TREE_CODE (decl) == FUNCTION_DECL && !TREE_PUBLIC (decl)) |
528 | ret_val = concat ("static " , ret_val, NULL); |
529 | |
530 | return ret_val; |
531 | } |
532 | |
533 | extern FILE *aux_info_file; |
534 | |
535 | /* Generate and write a new line of info to the aux-info (.X) file. This |
536 | routine is called once for each function declaration, and once for each |
537 | function definition (even the implicit ones). */ |
538 | |
539 | void |
540 | gen_aux_info_record (tree fndecl, int is_definition, int is_implicit, |
541 | int is_prototyped) |
542 | { |
543 | if (flag_gen_aux_info) |
544 | { |
545 | static int compiled_from_record = 0; |
546 | expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (fndecl)); |
547 | |
548 | /* Each output .X file must have a header line. Write one now if we |
549 | have not yet done so. */ |
550 | |
551 | if (!compiled_from_record++) |
552 | { |
553 | /* The first line tells which directory file names are relative to. |
554 | Currently, -aux-info works only for files in the working |
555 | directory, so just use a `.' as a placeholder for now. */ |
556 | fprintf (stream: aux_info_file, format: "/* compiled from: . */\n" ); |
557 | } |
558 | |
559 | /* Write the actual line of auxiliary info. */ |
560 | |
561 | fprintf (stream: aux_info_file, format: "/* %s:%d:%c%c */ %s;" , |
562 | xloc.file, xloc.line, |
563 | (is_implicit) ? 'I' : (is_prototyped) ? 'N' : 'O', |
564 | (is_definition) ? 'F' : 'C', |
565 | gen_decl (decl: fndecl, is_func_definition: is_definition, style: ansi)); |
566 | |
567 | /* If this is an explicit function declaration, we need to also write |
568 | out an old-style (i.e. K&R) function header, just in case the user |
569 | wants to run unprotoize. */ |
570 | |
571 | if (is_definition) |
572 | { |
573 | fprintf (stream: aux_info_file, format: " /*%s %s*/" , |
574 | gen_formal_list_for_func_def (fndecl, style: k_and_r_names), |
575 | gen_formal_list_for_func_def (fndecl, style: k_and_r_decls)); |
576 | } |
577 | |
578 | fprintf (stream: aux_info_file, format: "\n" ); |
579 | } |
580 | } |
581 | |