make.tmpl: add missing compiler attribute to build_progs
[AROS.git] / tools / genmodule / functionhead.c
blob2afd8fdbc6fd10d41a17954207fcb598e45ed86e
1 /*
2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
3 $Id$
5 The code for storing information of functions present in the module
6 */
7 #include <string.h>
8 #include <assert.h>
9 #include "functionhead.h"
10 #include "config.h"
12 struct functionhead *newfunctionhead(const char *name, enum libcall libcall)
14 struct functionhead *funchead = malloc(sizeof(struct functionhead));
16 if (funchead != NULL)
18 funchead->next = NULL;
19 funchead->internalname = funchead->name = strdup(name);
20 funchead->type = NULL;
21 funchead->libcall = libcall;
22 funchead->lvo = 0;
23 funchead->argcount = 0;
24 funchead->arguments = NULL;
25 funchead->aliases = NULL;
26 funchead->interface = NULL;
27 funchead->method = NULL;
28 funchead->novararg = 0;
29 funchead->priv= 0;
30 funchead->unusedlibbase = 0;
32 else
34 puts("Out of memory !");
35 exit(20);
38 return funchead;
41 struct functionarg *funcaddarg
43 struct functionhead *funchead,
44 const char *arg, const char *reg
47 struct functionarg **argptr = &funchead->arguments;
49 while ((*argptr) != NULL) argptr = &(*argptr)->next;
51 *argptr = malloc(sizeof(struct functionarg));
52 if (*argptr != NULL)
54 (*argptr)->next = NULL;
55 (*argptr)->arg = (arg == NULL) ? NULL : strdup(arg);
56 (*argptr)->reg = (reg == NULL) ? NULL : strdup(reg);
58 funchead->argcount++;
60 else
62 puts("Out of memory !");
63 exit(20);
66 return *argptr;
69 struct stringlist *funcaddalias(struct functionhead *funchead, const char *alias)
71 return slist_append(&funchead->aliases, alias);
74 void funcsetinternalname(struct functionhead *funchead, const char *internalname)
76 if (funchead->name != funchead->internalname)
77 free(funchead->internalname);
78 funchead->internalname = strdup(internalname);
81 void writefuncdefs(FILE *out, struct config *cfg, struct functionhead *funclist)
83 struct functionhead *funclistit;
84 struct functionarg *arglistit;
85 char *type, *name;
86 int first;
88 for(funclistit = funclist; funclistit != NULL; funclistit = funclistit->next)
90 switch (funclistit->libcall)
92 case STACK:
93 fprintf(out, "%s %s(", funclistit->type, funclistit->internalname);
95 for(arglistit = funclistit->arguments, first = 1;
96 arglistit != NULL;
97 arglistit = arglistit->next, first = 0
100 if (!first)
101 fprintf(out, ", ");
103 fprintf(out, "%s", arglistit->arg);
105 fprintf(out, ");\n");
106 break;
108 case REGISTER:
109 assert(cfg);
110 fprintf(out, "%s %s(", funclistit->type, funclistit->internalname);
111 for (arglistit = funclistit->arguments, first = 1;
112 arglistit!=NULL;
113 arglistit = arglistit->next, first = 0
116 if (!first)
117 fprintf(out, ", ");
118 fprintf(out, "%s", arglistit->arg);
120 fprintf(out,
121 ");\nAROS_LH%d%s(%s, %s,\n",
122 funclistit->argcount, funclistit->unusedlibbase ? "I" : "",
123 funclistit->type, funclistit->internalname
125 for (arglistit = funclistit->arguments;
126 arglistit!=NULL;
127 arglistit = arglistit->next
130 type = getargtype(arglistit);
131 name = getargname(arglistit);
132 assert(name != NULL && type != NULL);
134 fprintf(out,
135 " AROS_LHA(%s, %s, %s),\n",
136 type, name, arglistit->reg
138 free(type);
139 free(name);
141 fprintf(out,
142 " %s, %s, %u, %s)\n"
143 "{\n"
144 " AROS_LIBFUNC_INIT\n\n"
145 " %s%s(",
146 cfg->libbasetypeptrextern, cfg->libbase, funclistit->lvo, cfg->basename,
147 (strcasecmp(funclistit->type, "void") == 0) ? "" : "return ",
148 funclistit->internalname
150 for (arglistit = funclistit->arguments, first = 1;
151 arglistit!=NULL;
152 arglistit = arglistit->next, first = 0
155 name = getargname(arglistit);
156 assert(name != NULL);
158 if (!first)
159 fprintf(out, ", ");
160 fprintf(out, "%s", name);
161 free(name);
163 fprintf(out,
164 ");\n\n"
165 " AROS_LIBFUNC_EXIT\n"
166 "}\n\n");
167 break;
169 case REGISTERMACRO:
170 assert(cfg);
171 if (funclistit->arguments == NULL
172 || strchr(funclistit->arguments->reg, '/') == NULL)
174 fprintf(out,
175 "AROS_LD%d%s(%s, %s,\n",
176 funclistit->argcount, funclistit->unusedlibbase ? "I" : "",
177 funclistit->type, funclistit->internalname
179 for (arglistit = funclistit->arguments;
180 arglistit!=NULL;
181 arglistit = arglistit->next
184 type = getargtype(arglistit);
185 name = getargname(arglistit);
186 assert(type != NULL && name != NULL);
188 fprintf(out,
189 " AROS_LDA(%s, %s, %s),\n",
190 type, name, arglistit->reg
192 free(type);
193 free(name);
195 fprintf(out,
196 " LIBBASETYPEPTR, %s, %u, %s\n"
197 ");\n",
198 cfg->libbase, funclistit->lvo, cfg->basename
201 else
203 fprintf(out,
204 "AROS_LDQUAD%d(%s, %s,\n",
205 funclistit->argcount, funclistit->type, funclistit->internalname
207 for (arglistit = funclistit->arguments;
208 arglistit != NULL;
209 arglistit = arglistit->next
212 if (strlen(arglistit->reg) != 5)
214 fprintf(stderr, "Internal error: ../.. register format expected\n");
215 exit(20);
217 arglistit->reg[2] = 0;
219 type = getargtype(arglistit);
220 name = getargname(arglistit);
221 assert(type != NULL && name != NULL);
223 fprintf(out,
224 " AROS_LDAQUAD(%s, %s, %s, %s),\n",
225 type, name, arglistit->reg, arglistit->reg+3
227 arglistit->reg[2] = '/';
228 free(type);
229 free(name);
231 fprintf(out,
232 " LIBBASETYPEPTR, %s, %u, %s\n"
233 ");\n",
234 cfg->libbase, funclistit->lvo, cfg->basename
237 break;
239 default:
240 fprintf(stderr, "Internal error: unhandled libcall in writefuncdefs\n");
241 exit(20);
242 break;
247 void writefuncprotos(FILE *out, struct config *cfg, struct functionhead *funclist)
249 struct functionhead *funclistit;
250 struct functionarg *arglistit;
251 char *type, *name;
252 int first;
254 for(funclistit = funclist; funclistit != NULL; funclistit = funclistit->next)
256 fprintf(out,
257 "\n"
258 "#if !defined(__%s_LIBAPI__) || (%d <= __%s_LIBAPI__)"
259 "\n",
260 cfg->includenameupper,
261 funclistit->version,
262 cfg->includenameupper
265 switch (funclistit->libcall)
267 case STACK:
268 fprintf(
269 out,
270 "#ifndef %s\n"
271 "%s %s(",
272 funclistit->name,
273 funclistit->type, funclistit->name
276 for(arglistit = funclistit->arguments, first = 1;
277 arglistit != NULL;
278 arglistit = arglistit->next, first = 0
281 if (!first)
282 fprintf(out, ", ");
284 fprintf(out, "%s", arglistit->arg);
286 fprintf(out, ");\n#endif\n");
287 break;
289 case REGISTER:
290 case REGISTERMACRO:
291 assert(cfg);
292 if (funclistit->priv || funclistit->lvo < cfg->firstlvo) {
293 fprintf(out, "/* private */\n");
294 break;
297 if (funclistit->arguments == NULL
298 || strchr(funclistit->arguments->reg, '/') == NULL
301 fprintf(out,
302 "AROS_LP%d%s(%s, %s,\n",
303 funclistit->argcount, funclistit->unusedlibbase ? "I" : "",
304 funclistit->type, funclistit->name
306 for (arglistit = funclistit->arguments;
307 arglistit!=NULL;
308 arglistit = arglistit->next
311 type = getargtype(arglistit);
312 name = getargname(arglistit);
313 assert(type != NULL && name != NULL);
315 fprintf(out,
316 " AROS_LPA(%s, %s, %s),\n",
317 type, name, arglistit->reg
319 free(type);
320 free(name);
322 fprintf(out,
323 " LIBBASETYPEPTR, %s, %u, %s\n"
324 ");\n",
325 cfg->libbase, funclistit->lvo, cfg->basename
328 else
330 fprintf(out,
331 "AROS_LPQUAD%d(%s, %s,\n",
332 funclistit->argcount, funclistit->type, funclistit->name
334 for (arglistit = funclistit->arguments;
335 arglistit != NULL;
336 arglistit = arglistit->next
339 if (strlen(arglistit->reg) != 5)
341 fprintf(stderr, "Internal error: ../.. register format expected\n");
342 exit(20);
344 arglistit->reg[2] = 0;
346 type = getargtype(arglistit);
347 name = getargname(arglistit);
348 assert(type != NULL && name != NULL);
350 fprintf(out,
351 " AROS_LPAQUAD(%s, %s, %s, %s),\n",
352 type, name, arglistit->reg, arglistit->reg+3
354 arglistit->reg[2] = '/';
355 free(type);
356 free(name);
358 fprintf(out,
359 " LIBBASETYPEPTR, %s, %u, %s\n"
360 ");\n",
361 cfg->libbase, funclistit->lvo, cfg->basename
364 break;
366 default:
367 fprintf(stderr, "Internal error:"
368 " unhandled libcall in writefuncprotos\n");
369 exit(20);
370 break;
373 fprintf(out,
374 "\n"
375 "#endif /* !defined(__%s_LIBAPI__) || (%d <= __%s_LIBAPI__) */"
376 "\n",
377 cfg->includenameupper,
378 funclistit->version,
379 cfg->includenameupper
384 void writefuncinternalstubs(FILE *out, struct config *cfg, struct functionhead *funclist)
386 struct functionhead *funclistit;
387 struct functionarg *arglistit;
388 char *type, *name;
389 int first;
391 for(funclistit = funclist; funclistit != NULL; funclistit = funclistit->next)
393 switch (funclistit->libcall)
395 case STACK:
396 if ((cfg->options & OPTION_DUPBASE)
397 && !funclistit->unusedlibbase
400 fprintf(out,
401 "AROS_GM_STACKCALL(%s,%s,%d);\n"
402 , funclistit->internalname
403 , cfg->basename
404 , funclistit->lvo
407 else
409 fprintf(out,
410 "AROS_GM_STACKALIAS(%s,%s,%d);\n"
411 , funclistit->internalname
412 , cfg->basename
413 , funclistit->lvo
416 break;
418 case REGISTER:
419 case REGISTERMACRO:
420 /* NOP */
421 break;
423 default:
424 fprintf(stderr, "Internal error: "
425 "unhandled libcall in writefuncinternalstubs\n");
426 exit(20);
427 break;
432 char *getargtype(const struct functionarg *funcarg)
434 char *s, *begin, *end;
435 unsigned int brackets = 0, i;
437 begin = s = strdup(funcarg->arg);
439 /* Count the [] at the end of the argument */
440 end = begin+strlen(begin);
441 while (isspace(*(end-1))) end--;
442 while (*(end-1)==']')
444 brackets++;
445 end--;
446 while (isspace(*(end-1)) || isdigit(*(end-1))) end--;
447 if (*(end-1)!='[')
449 free(s);
450 return NULL;
452 end--;
453 while (isspace(*(end-1))) end--;
456 /* Skip over the argument name */
457 while (!isspace(*(end-1)) && *(end-1)!='*')
459 if (begin == end)
461 free(s);
462 fprintf(stderr, "no argument type or name found for arg: %s\n", funcarg->arg);
463 exit(20);
465 end--;
468 /* Add * for the brackets */
469 while (isspace(*(end-1))) end--;
470 for (i=0; i<brackets; i++)
472 *end='*';
473 end++;
475 *end='\0';
477 return s;
480 char *getargname(const struct functionarg *funcarg)
482 char *s, *begin, *end;
483 int len;
485 /* Count the [] at the end of the argument */
486 end = funcarg->arg+strlen(funcarg->arg);
487 while (isspace(*(end-1))) end--;
488 while (*(end-1)==']')
490 end--;
491 while (isspace(*(end-1))) end--;
492 if (*(end-1)!='[')
493 return NULL;
494 end--;
495 while (isspace(*(end-1))) end--;
498 /* Go to the beginning of the argument name */
499 begin = end;
500 while (!isspace(*(begin-1)) && *(begin-1)!='*') begin--;
502 /* Copy the name */
503 len = end - begin;
504 s = malloc(len+1);
505 strncpy(s, begin, len);
506 s[len] = '\0';
508 return s;