Mostly changes ported from ABIv0 branch:
[AROS.git] / tools / genmodule / functionhead.c
blob827b494bd693ca1519fca7c3e55b4effbab712d9
1 /*
2 Copyright © 1995-2012, 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->modulenameupper,
261 funclistit->version,
262 cfg->modulenameupper
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: unhandled libcall in writefuncdefs\n");
368 exit(20);
369 break;
372 fprintf(out,
373 "\n"
374 "#endif /* !defined(__%s_LIBAPI__) || (%d <= __%s_LIBAPI__) */"
375 "\n",
376 cfg->modulenameupper,
377 funclistit->version,
378 cfg->modulenameupper
383 void writefuncinternalstubs(FILE *out, struct config *cfg, struct functionhead *funclist)
385 struct functionhead *funclistit;
386 struct functionarg *arglistit;
387 char *type, *name;
388 int first;
390 for(funclistit = funclist; funclistit != NULL; funclistit = funclistit->next)
392 switch (funclistit->libcall)
394 case STACK:
395 if ((cfg->options & OPTION_DUPBASE)
396 && !funclistit->unusedlibbase
399 fprintf(out,
400 "AROS_GM_STACKCALL(%s,%s,%d);\n"
401 , funclistit->internalname
402 , cfg->basename
403 , funclistit->lvo
406 else
408 fprintf(out,
409 "AROS_GM_STACKALIAS(%s,%s,%d);\n"
410 , funclistit->internalname
411 , cfg->basename
412 , funclistit->lvo
415 break;
417 case REGISTER:
418 case REGISTERMACRO:
419 /* NOP */
420 break;
422 default:
423 fprintf(stderr, "Internal error: unhandled libcall in writefuncdefs\n");
424 exit(20);
425 break;
430 char *getargtype(const struct functionarg *funcarg)
432 char *s, *begin, *end;
433 unsigned int brackets = 0, i;
435 begin = s = strdup(funcarg->arg);
437 /* Count the [] at the end of the argument */
438 end = begin+strlen(begin);
439 while (isspace(*(end-1))) end--;
440 while (*(end-1)==']')
442 brackets++;
443 end--;
444 while (isspace(*(end-1)) || isdigit(*(end-1))) end--;
445 if (*(end-1)!='[')
447 free(s);
448 return NULL;
450 end--;
451 while (isspace(*(end-1))) end--;
454 /* Skip over the argument name */
455 while (!isspace(*(end-1)) && *(end-1)!='*')
457 if (begin == end)
459 free(s);
460 fprintf(stderr, "no argument type or name found for arg: %s\n", funcarg->arg);
461 exit(20);
463 end--;
466 /* Add * for the brackets */
467 while (isspace(*(end-1))) end--;
468 for (i=0; i<brackets; i++)
470 *end='*';
471 end++;
473 *end='\0';
475 return s;
478 char *getargname(const struct functionarg *funcarg)
480 char *s, *begin, *end;
481 int len;
483 /* Count the [] at the end of the argument */
484 end = funcarg->arg+strlen(funcarg->arg);
485 while (isspace(*(end-1))) end--;
486 while (*(end-1)==']')
488 end--;
489 while (isspace(*(end-1))) end--;
490 if (*(end-1)!='[')
491 return NULL;
492 end--;
493 while (isspace(*(end-1))) end--;
496 /* Go to the beginning of the argument name */
497 begin = end;
498 while (!isspace(*(begin-1)) && *(begin-1)!='*') begin--;
500 /* Copy the name */
501 len = end - begin;
502 s = malloc(len+1);
503 strncpy(s, begin, len);
504 s[len] = '\0';
506 return s;