Fix create_patch macro.
[AROS.git] / tools / genmodule / functionhead.c
blobcc38587c53bb739e22e1d54efe3c90b0fabe8a54
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 " return %s(",
146 cfg->libbasetypeptrextern, cfg->libbase, funclistit->lvo, cfg->basename,
147 funclistit->internalname
149 for (arglistit = funclistit->arguments, first = 1;
150 arglistit!=NULL;
151 arglistit = arglistit->next, first = 0
154 name = getargname(arglistit);
155 assert(name != NULL);
157 if (!first)
158 fprintf(out, ", ");
159 fprintf(out, "%s", name);
160 free(name);
162 fprintf(out,
163 ");\n\n"
164 " AROS_LIBFUNC_EXIT\n"
165 "}\n\n");
166 break;
168 case REGISTERMACRO:
169 assert(cfg);
170 if (funclistit->arguments == NULL
171 || strchr(funclistit->arguments->reg, '/') == NULL)
173 fprintf(out,
174 "AROS_LD%d%s(%s, %s,\n",
175 funclistit->argcount, funclistit->unusedlibbase ? "I" : "",
176 funclistit->type, funclistit->internalname
178 for (arglistit = funclistit->arguments;
179 arglistit!=NULL;
180 arglistit = arglistit->next
183 type = getargtype(arglistit);
184 name = getargname(arglistit);
185 assert(type != NULL && name != NULL);
187 fprintf(out,
188 " AROS_LDA(%s, %s, %s),\n",
189 type, name, arglistit->reg
191 free(type);
192 free(name);
194 fprintf(out,
195 " LIBBASETYPEPTR, %s, %u, %s\n"
196 ");\n",
197 cfg->libbase, funclistit->lvo, cfg->basename
200 else
202 fprintf(out,
203 "AROS_LDQUAD%d(%s, %s,\n",
204 funclistit->argcount, funclistit->type, funclistit->internalname
206 for (arglistit = funclistit->arguments;
207 arglistit != NULL;
208 arglistit = arglistit->next
211 if (strlen(arglistit->reg) != 5)
213 fprintf(stderr, "Internal error: ../.. register format expected\n");
214 exit(20);
216 arglistit->reg[2] = 0;
218 type = getargtype(arglistit);
219 name = getargname(arglistit);
220 assert(type != NULL && name != NULL);
222 fprintf(out,
223 " AROS_LDAQUAD(%s, %s, %s, %s),\n",
224 type, name, arglistit->reg, arglistit->reg+3
226 arglistit->reg[2] = '/';
227 free(type);
228 free(name);
230 fprintf(out,
231 " LIBBASETYPEPTR, %s, %u, %s\n"
232 ");\n",
233 cfg->libbase, funclistit->lvo, cfg->basename
236 break;
238 default:
239 fprintf(stderr, "Internal error: unhandled libcall in writefuncdefs\n");
240 exit(20);
241 break;
246 void writefuncprotos(FILE *out, struct config *cfg, struct functionhead *funclist)
248 struct functionhead *funclistit;
249 struct functionarg *arglistit;
250 char *type, *name;
251 int first;
253 for(funclistit = funclist; funclistit != NULL; funclistit = funclistit->next)
255 fprintf(out,
256 "\n"
257 "#if !defined(__%s_LIBAPI__) || (%d <= __%s_LIBAPI__)"
258 "\n",
259 cfg->modulenameupper,
260 funclistit->version,
261 cfg->modulenameupper
264 switch (funclistit->libcall)
266 case STACK:
267 fprintf(out, "%s %s(", funclistit->type, funclistit->name);
269 for(arglistit = funclistit->arguments, first = 1;
270 arglistit != NULL;
271 arglistit = arglistit->next, first = 0
274 if (!first)
275 fprintf(out, ", ");
277 fprintf(out, "%s", arglistit->arg);
279 fprintf(out, ");\n");
280 break;
282 case REGISTER:
283 case REGISTERMACRO:
284 assert(cfg);
285 if (funclistit->priv || funclistit->lvo < cfg->firstlvo) {
286 fprintf(out, "/* private */\n");
287 break;
290 if (funclistit->arguments == NULL
291 || strchr(funclistit->arguments->reg, '/') == NULL
294 fprintf(out,
295 "AROS_LP%d%s(%s, %s,\n",
296 funclistit->argcount, funclistit->unusedlibbase ? "I" : "",
297 funclistit->type, funclistit->name
299 for (arglistit = funclistit->arguments;
300 arglistit!=NULL;
301 arglistit = arglistit->next
304 type = getargtype(arglistit);
305 name = getargname(arglistit);
306 assert(type != NULL && name != NULL);
308 fprintf(out,
309 " AROS_LPA(%s, %s, %s),\n",
310 type, name, arglistit->reg
312 free(type);
313 free(name);
315 fprintf(out,
316 " LIBBASETYPEPTR, %s, %u, %s\n"
317 ");\n",
318 cfg->libbase, funclistit->lvo, cfg->basename
321 else
323 fprintf(out,
324 "AROS_LPQUAD%d(%s, %s,\n",
325 funclistit->argcount, funclistit->type, funclistit->name
327 for (arglistit = funclistit->arguments;
328 arglistit != NULL;
329 arglistit = arglistit->next
332 if (strlen(arglistit->reg) != 5)
334 fprintf(stderr, "Internal error: ../.. register format expected\n");
335 exit(20);
337 arglistit->reg[2] = 0;
339 type = getargtype(arglistit);
340 name = getargname(arglistit);
341 assert(type != NULL && name != NULL);
343 fprintf(out,
344 " AROS_LPAQUAD(%s, %s, %s, %s),\n",
345 type, name, arglistit->reg, arglistit->reg+3
347 arglistit->reg[2] = '/';
348 free(type);
349 free(name);
351 fprintf(out,
352 " LIBBASETYPEPTR, %s, %u, %s\n"
353 ");\n",
354 cfg->libbase, funclistit->lvo, cfg->basename
357 break;
359 default:
360 fprintf(stderr, "Internal error: unhandled libcall in writefuncdefs\n");
361 exit(20);
362 break;
365 fprintf(out,
366 "\n"
367 "#endif /* !defined(__%s_LIBAPI__) || (%d <= __%s_LIBAPI__) */"
368 "\n",
369 cfg->modulenameupper,
370 funclistit->version,
371 cfg->modulenameupper
376 void writefuncinternalstubs(FILE *out, struct config *cfg, struct functionhead *funclist)
378 struct functionhead *funclistit;
379 struct functionarg *arglistit;
380 char *type, *name;
381 int first;
383 for(funclistit = funclist; funclistit != NULL; funclistit = funclistit->next)
385 switch (funclistit->libcall)
387 case STACK:
388 if ((cfg->options & OPTION_DUPBASE)
389 && !funclistit->unusedlibbase
392 fprintf(out,
393 "AROS_GM_STACKCALL(%s,%s,%d);\n"
394 , funclistit->internalname
395 , cfg->basename
396 , funclistit->lvo
399 else
401 fprintf(out,
402 "AROS_GM_STACKALIAS(%s,%s,%d);\n"
403 , funclistit->internalname
404 , cfg->basename
405 , funclistit->lvo
408 break;
410 case REGISTER:
411 case REGISTERMACRO:
412 /* NOP */
413 break;
415 default:
416 fprintf(stderr, "Internal error: unhandled libcall in writefuncdefs\n");
417 exit(20);
418 break;
423 char *getargtype(const struct functionarg *funcarg)
425 char *s, *begin, *end;
426 unsigned int brackets = 0, i;
428 begin = s = strdup(funcarg->arg);
430 /* Count the [] at the end of the argument */
431 end = begin+strlen(begin);
432 while (isspace(*(end-1))) end--;
433 while (*(end-1)==']')
435 brackets++;
436 end--;
437 while (isspace(*(end-1)) || isdigit(*(end-1))) end--;
438 if (*(end-1)!='[')
440 free(s);
441 return NULL;
443 end--;
444 while (isspace(*(end-1))) end--;
447 /* Skip over the argument name */
448 while (!isspace(*(end-1)) && *(end-1)!='*')
450 if (begin == end)
452 free(s);
453 fprintf(stderr, "no argument type or name found for arg: %s\n", funcarg->arg);
454 exit(20);
456 end--;
459 /* Add * for the brackets */
460 while (isspace(*(end-1))) end--;
461 for (i=0; i<brackets; i++)
463 *end='*';
464 end++;
466 *end='\0';
468 return s;
471 char *getargname(const struct functionarg *funcarg)
473 char *s, *begin, *end;
474 int len;
476 /* Count the [] at the end of the argument */
477 end = funcarg->arg+strlen(funcarg->arg);
478 while (isspace(*(end-1))) end--;
479 while (*(end-1)==']')
481 end--;
482 while (isspace(*(end-1))) end--;
483 if (*(end-1)!='[')
484 return NULL;
485 end--;
486 while (isspace(*(end-1))) end--;
489 /* Go to the beginning of the argument name */
490 begin = end;
491 while (!isspace(*(begin-1)) && *(begin-1)!='*') begin--;
493 /* Copy the name */
494 len = end - begin;
495 s = malloc(len+1);
496 strncpy(s, begin, len);
497 s[len] = '\0';
499 return s;