tools/genmodule: Remember and restore memory slots in resp. OpenLib, CloseLib.
[AROS.git] / tools / genmodule / writestart.c
blob5577a9bcf73c34e3b3afc0bb4d8fe92fd296dafd
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Print the library magic and init code in the file modname_start.c.
6 This code is partly based on code in CLib37x.lha from Andreas R. Kleinert
7 */
8 #include "genmodule.h"
9 #include "oopsupport.h"
10 #include "muisupport.h"
11 #include "dtsupport.h"
12 #include "boopsisupport.h"
14 static void writedecl(FILE *, struct config *);
15 static void writedeclsets(FILE *, struct config *);
16 static void writeresident(FILE *, struct config *);
17 static void writeinitlib(FILE *, struct config *);
18 static void writehandler(FILE *, struct config *);
19 static void writeopenlib(FILE *, struct config *);
20 static void writecloselib(FILE *, struct config *);
21 static void writeexpungelib(FILE *, struct config *);
22 static void writeextfunclib(FILE *, struct config *);
23 static void writefunctable(FILE *, struct config *);
24 static void writesets(FILE *, struct config *);
26 /* Some general info on the function of the generated code and how they work
27 for .library modules (TODO: add docs for other module types):
29 The code in this file will write out the inittable, the function table,
30 the InitLib, OpenLib, CloseLib and ExpungeLib function.
31 InitLib will call the functions in the ADD2INIT symbolset.
32 OpenLib will call the functions in the ADD2OPENLIB symbolset.
33 CloseLib will call the functions in the ADD2CLOSELIB symbolset.
34 ExpungeLib will call the fucntions in the ADD2EXIT symbolset.
36 Currently 3 types of libraries are supported: 1 libbase, a per-opener
37 libbase and a per-task libbase.
38 * For 1 libbase the libbase is initialized once in InitLib and
39 then returned for each call to OpenLib. OpenLib and CloseLib keep track
40 of the times the libraries is still open; if it is 0 the library may be
41 expunged.
42 * The per-opener libbase will create a new libbase for each call to OpenLib
43 After InitLib has called the ADD2INIT functions the fields in the root
44 libbase may have been initialized to a certain value. These value are
45 copied in the newly generated libbase and then the ADD2OPENLIB functions
46 are called with the new libbase.
47 A per-opener libbase is indicated by the OPTION_DUPBASE flag in cfg->options.
48 Currently, a task memory slot is used to store the libbase when a function
49 of the library is entered. With proper support from the compiler this could
50 be changed to use a reserved register - probably increasing speed. This
51 could be implemented later on without breaking backwards compatibility.
52 Special provision has been taken to restore the state of the memory slot
53 after CloseLib to what it was when OpenLib is called. This is to handle the
54 case properly where the library is used both in the parent and child
55 of a Task run with RunCommand().
56 * The per-task libbase will create a new libbase for a call to OpenLib when
57 there does not exist a libbase yet for this task. This is handled by reserving
58 an additional task memory slot. In OpenLib the contents of this memory slot
59 is checked and only a new libbase will be generated when the libbase stored
60 there is not for the current Task. Also on then the ADD2OPENLIB
61 A separate counter is added to count the number of times the libbase is opened
62 in the same task. The libbase will also only be closed and removed if this
63 counter reaches 0 and only then the ADD2CLOSELIB functions are called.
64 A per-task libbase is indicated by both flags OPTION_DUPBASE and
65 OPTION_PERTASKBASE in cfg->options.
66 It was decided to use an extra slot for storing the per-task libbase to check
67 in OpenLib if a new libbase has to created. This is to increase flexibility
68 during calling of the library functions. If the library supports this the
69 library can still be called with another libbase then the libbase stored in the
70 per-task slot, or the library function can be called from another task then the
71 one that opened the libbase.
72 Also here special provision has been taken to restore the state of the memory
73 slot after CloseLib to what it was when OpenLib is called.
75 void writestart(struct config *cfg)
77 FILE *out;
78 char line[256], *banner;
79 struct classinfo *cl;
81 snprintf(line, 255, "%s/%s_start.c", cfg->gendir, cfg->modulename);
82 out = fopen(line, "w");
84 if (out == NULL)
86 perror(line);
87 exit(20);
90 banner = getBanner(cfg);
91 fprintf(out, "%s", banner);
92 freeBanner(banner);
94 fprintf(out,
95 "/* For comments and explanation of generated code look in writestart.c source code\n"
96 " of the genmodule program */\n"
99 writedecl(out, cfg);
100 if (!(cfg->options & OPTION_NORESIDENT))
102 writeresident(out, cfg);
103 writedeclsets(out, cfg);
104 writeinitlib(out, cfg);
105 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
107 writeopenlib(out, cfg);
108 writecloselib(out, cfg);
109 writeexpungelib(out, cfg);
110 writeextfunclib(out, cfg);
111 if (cfg->modtype == MCC || cfg->modtype == MUI || cfg->modtype == MCP)
112 writemccquery(out, cfg);
113 else if (cfg->modtype == DATATYPE)
114 writeobtainengine(out, cfg);
116 writesets(out, cfg);
119 if (cfg->modtype != HANDLER)
120 writefunctable(out, cfg);
122 for (cl = cfg->classlist; cl != NULL; cl = cl->next)
124 switch (cl->classtype)
126 case MCC:
127 case MUI:
128 case MCP:
129 /* Second argument to next call: the class is not the main class if it is not
130 * the first class or the modtype is not a MUI class
132 writemccinit(out, cl != cfg->classlist || cfg->modtype != cl->classtype, cl);
133 break;
134 case GADGET:
135 case DATATYPE:
136 case CLASS:
137 case IMAGE:
138 writeclassinit(out, cl);
139 break;
140 case HIDD:
141 writeoopinit(out, cl);
142 break;
143 default:
144 fprintf(stdout, "Internal error: unsupported classtype in writestart\n");
145 exit(20);
149 fclose(out);
153 static void writedecl(FILE *out, struct config *cfg)
155 struct stringlist *linelistit;
156 int boopsiinc=0, muiinc=0, oopinc=0;
157 struct functionhead *funclistit;
158 struct functionarg *arglistit;
159 struct classinfo *classlistit;
160 char *type, *name;
162 if (cfg->modtype == DEVICE)
164 fprintf(out,
165 "#include <exec/io.h>\n"
166 "#include <exec/errors.h>\n"
169 fprintf(out,
170 "#include <exec/types.h>\n"
171 "#include <exec/libraries.h>\n"
172 "#include <exec/resident.h>\n"
173 "#include <aros/libcall.h>\n"
174 "#include <aros/asmcall.h>\n"
175 "#include <aros/symbolsets.h>\n"
176 "#include <dos/dos.h>\n"
177 "\n"
178 "#include \"%s_libdefs.h\"\n"
179 "\n"
180 "#ifdef SysBase\n"
181 "#undef SysBase\n"
182 "#endif\n"
183 "\n"
184 "#include <proto/exec.h>\n"
185 "#include <proto/alib.h>\n"
186 "#ifndef __AROS__\n"
187 "struct ExecBase *SysBase = NULL;\n"
188 "#endif\n"
189 "\n",
190 cfg->modulename
193 /* Write out declaration section provided in the config file */
194 for (linelistit = cfg->cdeflines; linelistit != NULL; linelistit = linelistit->next)
196 fprintf(out, "%s\n", linelistit->s);
199 /* Is there a variable for storing the segList ? */
200 if (!(cfg->options & OPTION_NOEXPUNGE) && cfg->modtype!=RESOURCE && cfg->modtype != HANDLER)
202 fprintf(out,
203 "#ifndef GM_SEGLIST_FIELD\n"
204 "static BPTR __attribute__((unused)) GM_UNIQUENAME(seglist);\n"
205 "#define GM_SEGLIST_FIELD(lh) (GM_UNIQUENAME(seglist))\n"
206 "#endif\n"
209 if (cfg->options & OPTION_DUPBASE)
211 fprintf(out,
212 "#ifndef GM_ROOTBASE_FIELD\n"
213 "static LIBBASETYPEPTR GM_UNIQUENAME(rootbase);\n"
214 "#define GM_ROOTBASE_FIELD(lh) (GM_UNIQUENAME(rootbase))\n"
215 "#endif\n"
216 "static int __baseslot;\n"
217 "LIBBASETYPEPTR __GM_GetBase(void)\n"
218 "{\n"
219 " return (LIBBASETYPEPTR)SysBase->ThisTask->tc_UnionETask.tc_TaskStorage[__baseslot];\n"
220 "}\n"
221 /* On AMD64 don't clobber registers used for argument passing,
222 * only clobber rax, r10 and r11
224 "#if defined __x86_64__\n"
225 "asm(\".global __comp_get_relbase\\n\"\n"
226 " \"__comp_get_relbase :\\n\"\n"
227 " \"\\tmovq SysBase(%%rip), %%rax\\n\"\n"
228 " \"\\tmovq 552(%%rax), %%rax\\n\"\n"
229 " \"\\tmovq 56(%%rax), %%r10\\n\"\n"
230 " \"\\tmovslq __baseslot(%%rip),%%r11\\n\"\n"
231 " \"\\tmovq (%%r10,%%r11,8), %%rax\\n\"\n"
232 " \"\\tret\\n\"\n"
233 ");\n"
234 "#else\n"
235 "AROS_MAKE_ALIAS(__GM_GetBase, __comp_get_relbase);\n"
236 "#endif\n"
237 "static __used void __GM_SetBase(LIBBASETYPEPTR base)\n"
238 "{\n"
239 " SysBase->ThisTask->tc_UnionETask.tc_TaskStorage[__baseslot] = (IPTR)base;\n"
240 "}\n"
241 "#if defined __i386__\n"
242 "#define GM_INTERNALFUNCSTUB(fname)\\\n"
243 " asm(#fname \"_stub :\\n\"\\\n"
244 " \"\\tpushl %%eax\\n\"\\\n"
245 " \"\\tcall __GM_SetBase\\n\"\\\n"
246 " \"\\tpopl %%eax\\n\"\\\n"
247 " \"\\tjmp \" #fname \"\\n\"\\\n"
248 " )\n"
249 "#elif defined __x86_64__\n"
250 /* On AMD64 we can't call __GM_SetBase() as it will mess
251 * up with the parameters passed in registers
253 "#define GM_INTERNALFUNCSTUB(fname)\\\n"
254 /* On x86_64 we can use r10 and r11 in between function call and entry
255 r11 contains libbase */
256 " asm(#fname \"_stub :\\n\"\\\n"
257 " \"\\tpushq %%rax\\n\"\\\n"
258 " \"\\tmovq SysBase(%%rip), %%rax\\n\"\\\n"
259 " \"\\tmovslq __baseslot(%%rip),%%r10\\n\"\\\n"
260 " \"\\tmovq 552(%%rax), %%rax\\n\"\\\n"
261 " \"\\tmovq 56(%%rax), %%rax\\n\"\\\n"
262 " \"\\tmovq %%r11,(%%rax,%%r10,8)\\n\"\\\n"
263 " \"\\tpopq %%rax\\n\"\\\n"
264 " \"\\tjmp \" #fname \"\\n\"\\\n"
265 " )\n"
266 "#elif defined __mc68000__\n"
267 "#define GM_INTERNALFUNCSTUB(fname)\\\n"
268 " asm(#fname \"_stub :\\n\"\\\n"
269 " \"\\tmove.l %%a1,%%sp@-\\n\"\\\n"
270 " \"\\tjsr __GM_SetBase\\n\"\\\n"
271 " \"\\tmove.l %%sp@+,%%a1\\n\"\\\n"
272 " \"\\tjmp \" #fname \"\\n\"\\\n"
273 " )\n"
274 "#elif defined __powerpc__\n"
275 /* FIXME: struct offsets are from i386,
276 need to be checked ! */
277 "#define GM_INTERNALFUNCSTUB(fname)\\\n"
278 /* On PPC we can use r0, r11, r12 in between function call and entry
279 * r12 contains libbase
281 " asm(#fname \"_stub :\\n\"\\\n"
282 /* r0 = SysBase->ThisTask->tc_UnionETask.tc_TaskStorage */
283 " \"\\tlis 11, SysBase@ha\\n\"\\\n"
284 " \"\\tlwz 11, SysBase@l(11)\\n\"\\\n"
285 " \"\\tlwz 11, 284(11)\\n\"\\\n"
286 " \"\\tlwz 0, 36(11)\\n\"\\\n"
287 /* r11 = r0 + __baseslot */
288 " \"\\tlis 11, __baseslot@ha\\n\"\\\n"
289 " \"\\tlwz 11, __baseslot@l(11)\\n\"\\\n"
290 " \"\\tadd 11,0,11\\n\"\\\n"
291 /* *r11 = r12 (== libbase) */
292 " \"\\tstw 12, 0(11)\\n\"\\\n"
293 " \"\\tb \" #fname \"\\n\"\\\n"
294 " )\n"
295 "#elif defined __arm__\n"
296 "#define GM_INTERNALFUNCSTUB(fname)\\\n"
297 " asm(#fname \"_stub :\\n\"\\\n"
298 " \"\\tpush {r0, r1, r2, r3, lr}\\n\"\\\n"
299 " \"\\tmov r0, r12\\n\"\\\n"
300 " \"\\tbl __GM_SetBase\\n\"\\\n" /* r12 may be scratched */
301 " \"\\tpop {r0, r1, r2, r3, lr}\\n\"\\\n"
302 " \"\\tb \" #fname \"\\n\"\\\n" /* call function */
303 " )\n"
304 "#else\n"
305 "# error unsupported CPU type\n"
306 "#endif\n"
307 "struct __GM_DupBase {\n"
308 " LIBBASETYPE base;\n"
309 " LIBBASETYPEPTR oldbase;\n"
311 if (cfg->options & OPTION_PERTASKBASE)
313 fprintf(out,
314 " ULONG taskopencount;\n"
315 " struct Task *task;\n"
316 " APTR retaddr;\n"
317 " LIBBASETYPEPTR oldpertaskbase;\n"
320 fprintf(out,
321 "};\n"
322 "#define LIBBASESIZE sizeof(struct __GM_DupBase)\n"
324 if (cfg->options & OPTION_PERTASKBASE)
326 fprintf(out,
327 "static int __pertaskslot;\n"
328 "LIBBASETYPEPTR __GM_GetBaseParent(LIBBASETYPEPTR base)\n"
329 "{\n"
330 " return ((struct __GM_DupBase *)base)->oldpertaskbase;\n"
331 "}\n"
332 "static inline LIBBASETYPEPTR __GM_GetPerTaskBase(void)\n"
333 "{\n"
334 " return (LIBBASETYPEPTR)SysBase->ThisTask->tc_UnionETask.tc_TaskStorage[__pertaskslot];\n"
335 "}\n"
336 "static inline void __GM_SetPerTaskBase(LIBBASETYPEPTR base)\n"
337 "{\n"
338 " SysBase->ThisTask->tc_UnionETask.tc_TaskStorage[__pertaskslot] = (IPTR)base;\n"
339 "}\n"
343 else
344 fprintf(out, "#define LIBBASESIZE sizeof(LIBBASETYPE)\n");
346 for (classlistit = cfg->classlist; classlistit != NULL; classlistit = classlistit->next)
348 /* For the main class basename is the same as the module basename */
349 if (strcmp(classlistit->basename, cfg->basename) == 0)
351 if (classlistit->classptr_var == NULL)
353 fprintf(out,
354 "#if !defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
355 "static APTR GM_UNIQUENAME(%sClass);\n"
356 "#define GM_CLASSPTR_FIELD(lh) (GM_UNIQUENAME(%sClass))\n"
357 "#define %s_CLASSPTR_FIELD(lh) (GM_UNIQUENAME(%sClass))\n"
358 "#define %s_STORE_CLASSPTR 1\n"
359 "#elif defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
360 "#define %s_CLASSPTR_FIELD(lh) (GM_CLASSPTR_FIELD(lh))\n"
361 "#elif !defined(GM_CLASSPTR_FIELD) && defined(%s_CLASSPTR_FIELD)\n"
362 "#define GM_CLASSPTR_FIELD(lh) (%s_CLASSPTR_FIELD(lh))\n"
363 "#endif\n",
364 classlistit->basename,
365 classlistit->basename,
366 classlistit->basename,
367 classlistit->basename, classlistit->basename,
368 classlistit->basename,
369 classlistit->basename,
370 classlistit->basename,
371 classlistit->basename,
372 classlistit->basename
375 else
377 fprintf(out,
378 "#define GM_CLASSPTR_FIELD(lh) (%s)\n"
379 "#define %s_CLASSPTR_FIELD(lh) (%s)\n"
380 "#define %s_STORE_CLASSPTR 1\n",
381 classlistit->classptr_var,
382 classlistit->basename, classlistit->classptr_var,
383 classlistit->basename
387 else
389 if (classlistit->classptr_var == NULL)
391 fprintf(out,
392 "#if !defined(%s_CLASSPTR_FIELD)\n"
393 "static APTR GM_UNIQUENAME(%sClass);\n"
394 "#define %s_CLASSPTR_FIELD(lh) (GM_UNIQUENAME(%sClass))\n"
395 "#define %s_STORE_CLASSPTR 1\n"
396 "#endif\n",
397 classlistit->basename,
398 classlistit->basename,
399 classlistit->basename, classlistit->basename,
400 classlistit->basename
403 else
405 fprintf(out,
406 "#define %s_CLASSPTR_FIELD(lh) (%s)\n"
407 "#define %s_STORE_CLASSPTR 1\n",
408 classlistit->basename, classlistit->classptr_var,
409 classlistit->basename
415 /* Write out the defines for the functions of the function table */
416 writefuncdefs(out, cfg, cfg->funclist);
417 /* Write internal stubs */
418 writefuncinternalstubs(out, cfg, cfg->funclist);
419 fprintf(out, "\n");
422 /* Write out the includes needed for the classes */
423 if (cfg->classlist != NULL)
424 writeboopsiincludes(out);
426 for (classlistit = cfg->classlist; classlistit != NULL; classlistit = classlistit->next)
428 switch (classlistit->classtype)
430 case MUI:
431 case MCC:
432 case MCP:
433 if (!muiinc)
435 writemuiincludes(out);
436 muiinc = 1;
438 /* Fall through: also write boopsi includes */
439 case GADGET:
440 case DATATYPE:
441 case CLASS:
442 case IMAGE:
443 if (!boopsiinc)
445 writeboopsiincludes(out);
446 boopsiinc = 1;
448 break;
449 case HIDD:
450 if (!oopinc)
452 writeoopincludes(out);
453 oopinc = 1;
455 break;
456 default:
457 fprintf(stderr, "Internal error: unhandled classtype in writedecl\n");
458 exit(20);
464 static void writedeclsets(FILE *out, struct config *cfg)
466 fprintf(out,
467 "THIS_PROGRAM_HANDLES_SYMBOLSETS\n"
468 "DECLARESET(INIT)\n"
469 "DECLARESET(EXIT)\n"
470 "DECLARESET(CTORS)\n"
471 "DECLARESET(DTORS)\n"
472 "DECLARESET(INITLIB)\n"
473 "DECLARESET(EXPUNGELIB)\n"
475 if (!(cfg->options & OPTION_NOOPENCLOSE))
476 fprintf(out,
477 "DECLARESET(OPENLIB)\n"
478 "DECLARESET(CLOSELIB)\n"
480 if (cfg->modtype == DEVICE)
481 fprintf(out,
482 "DECLARESET(OPENDEV)\n"
483 "DECLARESET(CLOSEDEV)\n"
485 if (cfg->classlist != NULL)
486 fprintf(out,
487 "DECLARESET(CLASSESINIT)\n"
488 "DECLARESET(CLASSESEXPUNGE)\n"
489 "#define ADD2INITCLASSES(symbol, pri) ADD2SET(symbol, classesinit, pri)\n"
490 "#define ADD2EXPUNGECLASSES(symbol, pri) ADD2SET(symbol, classesexpunge, pri)\n"
492 fprintf(out, "\n");
496 static void writeresident(FILE *out, struct config *cfg)
498 char *rt_skip = cfg->addromtag;
500 if (rt_skip)
501 fprintf(out, "extern const struct Resident %s;\n", rt_skip);
502 else
504 rt_skip = "GM_UNIQUENAME(End)";
505 fprintf(out, "extern const int %s;\n", rt_skip);
507 fprintf(out,
508 "extern const APTR GM_UNIQUENAME(FuncTable)[];\n"
510 if (cfg->options & OPTION_RESAUTOINIT)
511 fprintf(out, "static const struct InitTable GM_UNIQUENAME(InitTable);\n");
512 fprintf(out,
513 "\n"
514 "extern const char GM_UNIQUENAME(LibName)[];\n"
515 "extern const char GM_UNIQUENAME(LibID)[];\n"
516 "extern const char GM_UNIQUENAME(Copyright)[];\n"
517 "\n"
520 if (cfg->options & OPTION_RESAUTOINIT)
522 fprintf(out,
523 "#define __freebase(lh)\\\n"
524 "do {\\\n"
525 " UWORD negsize, possize;\\\n"
526 " UBYTE *negptr = (UBYTE *)lh;\\\n"
527 " negsize = ((struct Library *)lh)->lib_NegSize;\\\n"
528 " negptr -= negsize;\\\n"
529 " possize = ((struct Library *)lh)->lib_PosSize;\\\n"
530 " FreeMem (negptr, negsize+possize);\\\n"
531 "} while(0)\n"
532 "\n");
535 fprintf(out,
536 "AROS_UFP3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
537 " AROS_UFPA(LIBBASETYPEPTR, lh, D0),\n"
538 " AROS_UFPA(BPTR, segList, A0),\n"
539 " AROS_UFPA(struct ExecBase *, sysBase, A6)\n"
540 ");\n"
542 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
544 fprintf(out,
545 "AROS_LD1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
546 " AROS_LDA(LIBBASETYPEPTR, extralh, D0),\n"
547 " LIBBASETYPEPTR, lh, 3, %s\n"
548 ");\n"
549 "\n",
550 cfg->basename
553 fprintf(out,
554 "struct Resident const GM_UNIQUENAME(ROMTag) =\n"
555 "{\n"
556 " RTC_MATCHWORD,\n"
557 " (struct Resident *)&GM_UNIQUENAME(ROMTag),\n"
558 " (APTR)&%s,\n"
559 " RESIDENTFLAGS,\n"
560 " VERSION_NUMBER,\n",
561 rt_skip
563 switch (cfg->modtype)
565 case LIBRARY:
566 case MUI:
567 case MCC:
568 case MCP:
569 case GADGET:
570 case DATATYPE:
571 case USBCLASS:
572 case HIDD:
573 fprintf(out, " NT_LIBRARY,\n");
574 break;
575 case DEVICE:
576 fprintf(out, " NT_DEVICE,\n");
577 break;
578 case RESOURCE:
579 case HANDLER:
580 fprintf(out, " NT_RESOURCE,\n");
581 break;
582 default:
583 fprintf(stderr, "Internal error: unsupported modtype for NT_...\n");
584 exit(20);
585 break;
587 fprintf(out,
588 " RESIDENTPRI,\n"
589 " (CONST_STRPTR)&GM_UNIQUENAME(LibName)[0],\n"
590 " (CONST_STRPTR)&GM_UNIQUENAME(LibID)[6],\n"
592 if (cfg->options & OPTION_RESAUTOINIT)
594 fprintf(out,
595 " (APTR)&GM_UNIQUENAME(InitTable)\n"
596 "};\n"
597 "\n"
598 "static struct InitTable\n"
599 "{\n"
600 " IPTR Size;\n"
601 " const APTR *FuncTable;\n"
602 " struct DataTable *DataTable;\n"
603 " APTR InitLibTable;\n"
604 "}\n"
605 "const GM_UNIQUENAME(InitTable) =\n"
606 "{\n"
607 " LIBBASESIZE,\n"
608 " &GM_UNIQUENAME(FuncTable)[0],\n"
609 " NULL,\n"
610 " (APTR)GM_UNIQUENAME(InitLib)\n"
611 "};\n"
614 else
615 fprintf(out, " (APTR)GM_UNIQUENAME(InitLib)\n};\n");
617 fprintf(out,
618 "\n"
619 "const char GM_UNIQUENAME(LibName)[] = MOD_NAME_STRING;\n"
620 "const char GM_UNIQUENAME(LibID)[] = VERSION_STRING;\n"
621 "const char GM_UNIQUENAME(Copyright)[] = COPYRIGHT_STRING;\n"
622 "\n"
626 static void writehandler(FILE *out, struct config *cfg)
628 int i;
629 struct handlerinfo *hl;
631 fprintf(out,
632 "\n"
633 "#include <resources/filesysres.h>\n"
634 "#include <aros/system.h>\n"
635 "#include <proto/arossupport.h>\n"
636 "#include <proto/dos.h>\n"
637 "\n"
640 for (hl = cfg->handlerlist; hl != NULL; hl = hl->next) {
641 fprintf(out,
642 "extern void %s(void);\n",
643 hl->handler);
646 fprintf(out,
647 "\n"
648 "void GM_UNIQUENAME(InitHandler)(void)\n"
649 "{\n"
650 " struct FileSysResource *fsr;\n"
651 " int i;\n"
652 " const struct {\n"
653 " ULONG id;\n"
654 " BSTR name;\n"
655 " BYTE autodetect;\n"
656 " BYTE priority;\n"
657 " ULONG stacksize;\n"
658 " void (*handler)(void);\n"
659 " } const __handler[] = { \n");
660 for (hl = cfg->handlerlist; hl != NULL; hl = hl->next)
662 switch (hl->type)
664 case HANDLER_RESIDENT:
665 fprintf(out,
666 " { .id = 0, .name = AROS_CONST_BSTR(\"%s\"), .handler = %s }, \n",
667 hl->name, hl->handler);
668 break;
669 case HANDLER_DOSTYPE:
670 fprintf(out,
671 " { .id = 0x%08x, .name = AROS_CONST_BSTR(MOD_NAME_STRING), .handler = %s, .autodetect = %d, .priority = %d, .stacksize = %d*sizeof(IPTR) }, \n",
672 hl->id, hl->handler, hl->autodetect, hl->priority, hl->stacksize);
673 break;
676 fprintf(out,
677 " };\n"
678 " BPTR seg[sizeof(__handler)/sizeof(__handler[0])] = { };\n"
679 "\n"
680 " fsr = (struct FileSysResource *)OpenResource(\"FileSystem.resource\");\n"
681 " if (fsr == NULL)\n"
682 " return;\n"
683 "\n"
684 " for (i = 0; i < sizeof(__handler)/sizeof(__handler[0]); i++) {\n"
685 " struct FileSysEntry *fse;\n"
686 " int j;\n"
687 "\n"
688 " /* Check to see if we can allocate the memory for the fse */\n"
689 " fse = AllocMem(sizeof(*fse), MEMF_CLEAR);\n"
690 " if (!fse)\n"
691 " return;\n"
692 "\n"
693 " /* Did we already make a segment for this handler? */\n"
694 " for (j = 0; j < i; j++)\n"
695 " if (__handler[i].handler == __handler[j].handler)\n"
696 " break;\n"
697 " if (seg[j] == (BPTR)0)\n"
698 " seg[j] = CreateSegList(__handler[j].handler);\n"
699 " if (seg[j] == BNULL) {\n"
700 " FreeMem(fse, sizeof(*fse));\n"
701 " return;\n"
702 " }\n"
703 " \n"
704 " /* DOS ID based handlers\n"
705 " * NOTE: fse_DosType == 0 is a special flag use in\n"
706 " * dos.library's init to add the handler to the\n"
707 " * resident segment list\n"
708 " */\n"
709 " fse->fse_Node.ln_Name = VERSION_STRING;\n"
710 " fse->fse_Node.ln_Pri = __handler[i].autodetect;\n"
711 " fse->fse_DosType = __handler[i].id;\n"
712 " fse->fse_Version = (MAJOR_VERSION << 16) | MINOR_VERSION;\n"
713 " fse->fse_PatchFlags = FSEF_SEGLIST | FSEF_GLOBALVEC | FSEF_HANDLER | FSEF_PRIORITY;\n"
714 " if (__handler[i].stacksize) {\n"
715 " fse->fse_PatchFlags |= FSEF_STACKSIZE;\n"
716 " fse->fse_StackSize = __handler[i].stacksize;\n"
717 " }\n"
718 " fse->fse_Handler = __handler[i].name;\n"
719 " fse->fse_Priority = __handler[i].priority;\n"
720 " fse->fse_SegList = seg[j];\n"
721 " fse->fse_GlobalVec = (BPTR)(SIPTR)-1;\n"
722 " \n"
723 " /* Add to the list. I know forbid and permit are\n"
724 " * a little unnecessary for the pre-multitasking state\n"
725 " * we should be in at this point, but you never know\n"
726 " * who's going to blindly copy this code as an example.\n"
727 " */\n"
728 " Forbid();\n"
729 " Enqueue(&fsr->fsr_FileSysEntries, (struct Node *)fse);\n"
730 " Permit();\n"
731 " }\n"
732 "}\n");
735 static void writeinitlib(FILE *out, struct config *cfg)
737 if (cfg->handlerlist)
738 writehandler(out, cfg);
740 fprintf(out,
741 "AROS_UFH3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
742 " AROS_UFHA(LIBBASETYPEPTR, lh, D0),\n"
743 " AROS_UFHA(BPTR, segList, A0),\n"
744 " AROS_UFHA(struct ExecBase *, sysBase, A6)\n"
745 ")\n"
746 "{\n"
747 " AROS_USERFUNC_INIT\n"
748 "\n"
749 " int ok;\n"
751 if (cfg->modtype != HANDLER)
752 fprintf(out,
753 " int initcalled = 0;\n"
755 fprintf(out,
756 "\n"
759 if (cfg->options & OPTION_RESAUTOINIT) {
760 fprintf(out,
761 "#ifndef __AROS__\n"
762 " SysBase = sysBase;\n"
763 "#endif\n"
764 "#ifdef GM_SYSBASE_FIELD\n"
765 " GM_SYSBASE_FIELD(lh) = (APTR)sysBase;\n"
766 "#endif\n"
767 "#ifdef GM_OOPBASE_FIELD\n"
768 " GM_OOPBASE_FIELD(lh) = OpenLibrary(\"oop.library\",0);\n"
769 " if (GM_OOPBASE_FIELD(lh) == NULL)\n"
770 " return NULL;\n"
771 "#endif\n"
775 if (cfg->modtype != HANDLER)
777 if (!(cfg->options & OPTION_RESAUTOINIT))
779 fprintf(out,
780 " int vecsize;\n"
781 " struct Node *n;\n"
782 " char *mem;\n"
783 "\n"
784 " vecsize = FUNCTIONS_COUNT * LIB_VECTSIZE;\n"
785 " if (vecsize > 0)\n"
786 " vecsize = ((vecsize-1)/sizeof(IPTR) + 1)*sizeof(IPTR);\n"
787 " mem = AllocMem(vecsize+sizeof(LIBBASETYPE), MEMF_PUBLIC|MEMF_CLEAR);\n"
788 " if (mem == NULL)\n"
789 " return NULL;\n"
790 " lh = (LIBBASETYPEPTR)(mem + vecsize);\n"
791 " n = (struct Node *)lh;\n"
792 " n->ln_Type = NT_RESOURCE;\n"
793 " n->ln_Pri = RESIDENTPRI;\n"
794 " n->ln_Name = (char *)GM_UNIQUENAME(LibName);\n"
795 " MakeFunctions(lh, (APTR)GM_UNIQUENAME(FuncTable), NULL);\n"
797 if ((cfg->modtype != RESOURCE) && (cfg->options & OPTION_SELFINIT))
799 fprintf(out,
800 " ((struct Library*)lh)->lib_NegSize = vecsize;\n"
801 " ((struct Library*)lh)->lib_PosSize = sizeof(LIBBASETYPE);\n"
806 else
808 fprintf(out,
809 " ((struct Library *)lh)->lib_Revision = REVISION_NUMBER;\n"
814 if (cfg->options & OPTION_DUPBASE)
815 fprintf(out,
816 " __baseslot = AllocTaskStorageSlot();\n"
817 " __GM_SetBase(lh);\n"
819 if (cfg->options & OPTION_PERTASKBASE)
820 fprintf(out,
821 " __pertaskslot = AllocTaskStorageSlot();\n"
824 if (!(cfg->options & OPTION_NOEXPUNGE) && cfg->modtype!=RESOURCE && cfg->modtype != HANDLER)
825 fprintf(out, " GM_SEGLIST_FIELD(lh) = segList;\n");
826 if (cfg->options & OPTION_DUPBASE)
827 fprintf(out, " GM_ROOTBASE_FIELD(lh) = (LIBBASETYPEPTR)lh;\n");
828 fprintf(out, " if (");
829 if (!(cfg->options & OPTION_NOAUTOLIB))
830 fprintf(out, "set_open_libraries() && ");
831 if (cfg->classlist != NULL)
832 fprintf(out, "set_call_libfuncs(SETNAME(CLASSESINIT), 1, 1, lh) && ");
833 fprintf(out,
834 "set_call_funcs(SETNAME(INIT), 1, 1) )\n"
835 " {\n"
836 " set_call_funcs(SETNAME(CTORS), -1, 0);\n"
837 "\n"
840 if (cfg->modtype == HANDLER)
841 fprintf(out,
842 " ok = 1;\n");
843 else
844 fprintf(out,
845 " initcalled = 1;\n"
846 " ok = set_call_libfuncs(SETNAME(INITLIB), 1, 1, lh);\n");
847 fprintf(out,
848 " }\n"
849 " else\n"
850 " ok = 0;\n"
851 "\n"
852 " if (!ok)\n"
853 " {\n"
856 if (cfg->modtype != HANDLER)
857 fprintf(out,
858 " if (initcalled)\n"
859 " set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 0, lh);\n");
861 fprintf(out,
862 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
863 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
865 if (cfg->classlist != NULL)
866 fprintf(out, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, lh);\n");
867 if (!(cfg->options & OPTION_NOAUTOLIB))
868 fprintf(out, " set_close_libraries();\n");
870 if (cfg->modtype != HANDLER)
872 if (cfg->options & OPTION_RESAUTOINIT)
874 fprintf(out,
875 "\n"
876 " __freebase(lh);\n"
879 else
881 fprintf(out,
882 "\n"
883 " FreeMem(mem, vecsize+LIBBASESIZE);\n"
887 fprintf(out,
888 " return NULL;\n"
889 " }\n"
890 " else\n"
891 " {\n"
894 if (!(cfg->options & OPTION_RESAUTOINIT) && !(cfg->options & OPTION_SELFINIT))
896 switch (cfg->modtype)
898 case RESOURCE:
899 fprintf(out, " AddResource(lh);\n");
900 break;
902 case DEVICE:
903 fprintf(out, " AddDevice(lh);\n");
905 case HANDLER:
906 /* Bare handlers don't require adding at all */
907 break;
909 default:
910 /* Everything else is library */
911 fprintf(out, " AddLibrary(lh);\n");
912 break;
916 if (cfg->handlerlist)
917 fprintf(out, " GM_UNIQUENAME(InitHandler)();\n");
919 fprintf(out,
920 " return lh;\n"
921 " }\n"
922 "\n"
923 " AROS_USERFUNC_EXIT\n"
924 "}\n"
925 "\n"
929 static void writeopenlib(FILE *out, struct config *cfg)
931 switch (cfg->modtype)
933 case RESOURCE:
934 fprintf(stderr, "Internal error: writeopenlib called for a resource\n");
935 break;
936 case HANDLER:
937 fprintf(stderr, "Internal error: writeopenlib called for a handler\n");
938 break;
939 case DEVICE:
940 if (cfg->options & OPTION_NOOPENCLOSE)
941 fprintf(out,
942 "AROS_LD3 (void, GM_UNIQUENAME(OpenLib),\n"
943 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
944 " AROS_LDA(ULONG, unitnum, D0),\n"
945 " AROS_LDA(ULONG, flags, D1),\n"
946 " LIBBASETYPEPTR, lh, 1, %s\n"
947 ");\n",
948 cfg->basename
950 else
952 fprintf(out,
953 "AROS_LH3 (void, GM_UNIQUENAME(OpenLib),\n"
954 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
955 " AROS_LHA(IPTR, unitnum, D0),\n"
956 " AROS_LHA(ULONG, flags, D1),\n"
957 " LIBBASETYPEPTR, lh, 1, %s\n"
958 ")\n",
959 cfg->basename
961 fprintf(out,
962 "{\n"
963 " AROS_LIBFUNC_INIT\n"
964 "\n"
965 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, lh)\n"
966 " && set_call_devfuncs(SETNAME(OPENDEV), 1, 1, lh, ioreq, unitnum, flags)\n"
967 " )\n"
968 " {\n"
969 " ((struct Library *)lh)->lib_OpenCnt++;\n"
970 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
971 "\n"
972 " ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;\n"
973 " }\n"
974 " else\n"
975 " {\n"
976 " if (ioreq->io_Error >= 0)\n"
977 " ioreq->io_Error = IOERR_OPENFAIL;\n"
978 " }\n"
979 "\n"
980 " return;\n"
981 "\n"
982 " AROS_LIBFUNC_EXIT\n"
983 "}\n"
984 "\n"
987 break;
988 default:
989 if (cfg->options & OPTION_NOOPENCLOSE)
991 fprintf(out,
992 "AROS_LD1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
993 " AROS_LDA (ULONG, version, D0),\n"
994 " LIBBASETYPEPTR, lh, 1, %s\n"
995 ");\n",
996 cfg->basename
998 return;
1000 fprintf(out,
1001 "AROS_LH1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
1002 " AROS_LHA (ULONG, version, D0),\n"
1003 " LIBBASETYPEPTR, lh, 1, %s\n"
1004 ")\n"
1005 "{\n"
1006 " AROS_LIBFUNC_INIT\n"
1007 "\n",
1008 cfg->basename
1010 if (!(cfg->options & OPTION_DUPBASE))
1012 fprintf(out,
1013 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, lh) )\n"
1014 " {\n"
1015 " ((struct Library *)lh)->lib_OpenCnt++;\n"
1016 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
1017 "\n"
1018 " return lh;\n"
1019 " }\n"
1020 "\n"
1021 " return NULL;\n"
1022 "\n"
1023 " AROS_LIBFUNC_EXIT\n"
1024 "}\n"
1025 "\n"
1028 else /* OPTION_DUPBASE */
1030 fprintf(out,
1031 " struct Library *newlib = NULL;\n"
1032 " UWORD possize = ((struct Library *)lh)->lib_PosSize;\n"
1033 " LIBBASETYPEPTR oldbase = __GM_GetBase();\n"
1035 if (cfg->options & OPTION_PERTASKBASE)
1036 fprintf(out,
1037 " struct Task *thistask = FindTask(NULL);\n"
1038 " LIBBASETYPEPTR oldpertaskbase = __GM_GetPerTaskBase();\n"
1039 " newlib = (struct Library *)oldpertaskbase;\n"
1040 " if (newlib)\n"
1041 " {\n"
1042 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1043 " if (dupbase->task != thistask)\n"
1044 " newlib = NULL;\n"
1045 " else if (thistask->tc_Node.ln_Type == NT_PROCESS\n"
1046 " && dupbase->retaddr != ((struct Process *)thistask)->pr_ReturnAddr\n"
1047 " )\n"
1048 " newlib = NULL;\n"
1049 " else\n"
1050 " dupbase->taskopencount++;\n"
1051 " }\n"
1054 fprintf(out,
1055 "\n"
1056 " if (newlib == NULL)\n"
1057 " {\n"
1058 " newlib = MakeLibrary(GM_UNIQUENAME(InitTable).FuncTable,\n"
1059 " GM_UNIQUENAME(InitTable).DataTable,\n"
1060 " NULL,\n"
1061 " GM_UNIQUENAME(InitTable).Size,\n"
1062 " (BPTR)NULL\n"
1063 " );\n"
1064 " if (newlib == NULL)\n"
1065 " return NULL;\n"
1066 "\n"
1067 " CopyMem(lh, newlib, possize);\n"
1068 " __GM_SetBase((LIBBASETYPEPTR)newlib);\n"
1069 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1070 " dupbase->oldbase = oldbase;\n"
1072 if (cfg->options & OPTION_PERTASKBASE)
1073 fprintf(out,
1074 " dupbase->task = thistask;\n"
1075 " if (thistask->tc_Node.ln_Type == NT_PROCESS)\n"
1076 " dupbase->retaddr = ((struct Process *)thistask)->pr_ReturnAddr;\n"
1077 " dupbase->oldpertaskbase = oldpertaskbase;\n"
1078 " dupbase->taskopencount = 1;\n"
1079 " __GM_SetPerTaskBase((LIBBASETYPEPTR)newlib);\n"
1081 fprintf(out,
1082 "\n"
1083 " if (!(set_open_rellibraries(newlib)\n"
1084 " && set_call_libfuncs(SETNAME(OPENLIB), 1, 1, newlib)\n"
1085 " )\n"
1086 " )\n"
1087 " {\n");
1088 if (cfg->options & OPTION_PERTASKBASE)
1089 fprintf(out,
1090 " __GM_SetPerTaskBase(oldpertaskbase);\n");
1091 fprintf(out,
1092 " __freebase(newlib);\n"
1093 " return NULL;\n"
1094 " }\n"
1095 "\n"
1096 " ((struct Library *)lh)->lib_OpenCnt++;\n"
1097 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
1098 " }\n"
1099 "\n"
1100 " return (LIBBASETYPEPTR)newlib;\n"
1101 "\n"
1102 " AROS_LIBFUNC_EXIT\n"
1103 "}\n"
1104 "\n"
1111 static void writecloselib(FILE *out, struct config *cfg)
1113 if (cfg->options & OPTION_NOOPENCLOSE)
1115 if (cfg->modtype != DEVICE)
1116 fprintf(out,
1117 "AROS_LD0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1118 " LIBBASETYPEPTR, lh, 2, %s\n"
1119 ");\n",
1120 cfg->basename
1122 else
1123 fprintf(out,
1124 "AROS_LD1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1125 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1126 " LIBBASETYPEPTR, lh, 2, %s\n"
1127 ");\n",
1128 cfg->basename
1130 return;
1132 if (cfg->modtype != DEVICE)
1133 fprintf(out,
1134 "AROS_LH0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1135 " LIBBASETYPEPTR, lh, 2, %s\n"
1136 ")\n",
1137 cfg->basename
1139 else
1140 fprintf(out,
1141 "AROS_LH1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1142 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1143 " LIBBASETYPEPTR, lh, 2, %s\n"
1144 ")\n",
1145 cfg->basename
1148 fprintf(out,
1149 "{\n"
1150 " AROS_LIBFUNC_INIT\n"
1151 "\n"
1153 if (cfg->modtype == DEVICE)
1154 fprintf(out,
1155 " if (!set_call_devfuncs(SETNAME(CLOSEDEV), -1, 1, lh, ioreq, 0, 0))\n"
1156 " {\n"
1157 " return BNULL;\n"
1158 " }\n"
1160 if (!(cfg->options & OPTION_DUPBASE))
1162 fprintf(out,
1163 " ((struct Library *)lh)->lib_OpenCnt--;\n"
1164 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, lh);\n"
1167 else /* OPTION_DUPBASE */
1169 fprintf(out,
1170 " LIBBASETYPEPTR rootbase = GM_ROOTBASE_FIELD(lh);\n"
1171 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)lh;\n"
1173 if (cfg->options & OPTION_PERTASKBASE)
1174 fprintf(out,
1175 " dupbase->taskopencount--;\n"
1176 " if (dupbase->taskopencount != 0)\n"
1177 " return BNULL;\n"
1179 fprintf(out,
1180 "\n"
1181 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, lh);\n"
1182 " set_close_rellibraries(lh);\n"
1183 " __GM_SetBase(dupbase->oldbase);\n"
1185 if (cfg->options & OPTION_PERTASKBASE)
1186 fprintf(out,
1187 " __GM_SetPerTaskBase(((struct __GM_DupBase *)lh)->oldpertaskbase);\n"
1189 fprintf(out,
1190 " __freebase(lh);\n"
1191 " lh = rootbase;\n"
1192 " ((struct Library *)lh)->lib_OpenCnt--;\n"
1193 "\n"
1196 if (!(cfg->options & OPTION_NOEXPUNGE))
1197 fprintf(out,
1198 " if\n"
1199 " (\n"
1200 " (((struct Library *)lh)->lib_OpenCnt == 0)\n"
1201 " && (((struct Library *)lh)->lib_Flags & LIBF_DELEXP)\n"
1202 " )\n"
1203 " {\n"
1204 " return AROS_LC1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1205 " AROS_LCA(LIBBASETYPEPTR, lh, D0),\n"
1206 " LIBBASETYPEPTR, lh, 3, %s\n"
1207 " );\n"
1208 " }\n",
1209 cfg->basename
1211 fprintf(out,
1212 "\n"
1213 " return BNULL;\n"
1214 "\n"
1215 " AROS_LIBFUNC_EXIT\n"
1216 "}\n"
1217 "\n"
1222 static void writeexpungelib(FILE *out, struct config *cfg)
1224 fprintf(out,
1225 "AROS_LH1 (BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1226 " AROS_LHA(LIBBASETYPEPTR, extralh, D0),\n"
1227 " LIBBASETYPEPTR, lh, 3, %s\n"
1228 ")\n",
1229 cfg->basename
1231 fprintf(out,
1232 "{\n"
1233 " AROS_LIBFUNC_INIT\n"
1234 "\n"
1236 if (!(cfg->options & OPTION_NOEXPUNGE))
1238 fprintf(out,
1239 "\n"
1240 " if ( ((struct Library *)lh)->lib_OpenCnt == 0 )\n"
1241 " {\n"
1242 " BPTR seglist = GM_SEGLIST_FIELD(lh);\n"
1243 "\n"
1244 " if(!set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 1, lh))\n"
1245 " {\n"
1246 " ((struct Library *)lh)->lib_Flags |= LIBF_DELEXP;\n"
1247 " return BNULL;\n"
1248 " }\n"
1249 "\n"
1250 " Remove((struct Node *)lh);\n"
1251 "\n"
1252 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
1253 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
1255 if (cfg->classlist != NULL)
1256 fprintf(out, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, lh);\n");
1257 if (!(cfg->options & OPTION_NOAUTOLIB))
1258 fprintf(out, " set_close_libraries();\n"
1259 "#ifdef GM_OOPBASE_FIELD\n"
1260 " CloseLibrary((struct Library *)GM_OOPBASE_FIELD(lh));\n"
1261 "#endif\n"
1263 if (cfg->options & OPTION_PERTASKBASE)
1264 fprintf(out,
1265 " FreeTaskStorageSlot(__pertaskslot);\n"
1266 " __pertaskslot = 0;\n"
1268 fprintf(out,
1269 "\n"
1270 " __freebase(lh);\n"
1271 "\n"
1272 " return seglist;\n"
1273 " }\n"
1274 "\n"
1275 " ((struct Library *)lh)->lib_Flags |= LIBF_DELEXP;\n"
1278 fprintf(out,
1279 "\n"
1280 " return BNULL;\n"
1281 "\n"
1282 " AROS_LIBFUNC_EXIT\n"
1283 "}\n"
1284 "\n"
1289 static void writeextfunclib(FILE *out, struct config *cfg)
1291 fprintf(out,
1292 "AROS_LH0 (LIBBASETYPEPTR, GM_UNIQUENAME(ExtFuncLib),\n"
1293 " LIBBASETYPEPTR, lh, 4, %s\n"
1294 ")\n"
1295 "{\n"
1296 " AROS_LIBFUNC_INIT\n"
1297 " return NULL;\n"
1298 " AROS_LIBFUNC_EXIT\n"
1299 "}\n"
1300 "\n",
1301 cfg->basename
1306 static void
1307 writefunctable(FILE *out,
1308 struct config *cfg
1311 struct functionhead *funclistit = cfg->funclist;
1312 struct functionarg *arglistit;
1313 unsigned int lvo;
1314 int i;
1315 char *name, *type;
1316 int lastversion = 0;
1318 /* lvo contains the number of functions already printed in the functable */
1319 lvo = 0;
1321 if (!(cfg->options & OPTION_NORESIDENT))
1323 fprintf(out,
1324 "\n"
1325 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1326 "{\n"
1328 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
1330 fprintf(out,
1331 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(OpenLib),%s,1),\n"
1332 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(CloseLib),%s,2),\n"
1333 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExpungeLib),%s,3),\n"
1334 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExtFuncLib),%s,4),\n",
1335 cfg->basename, cfg->basename, cfg->basename, cfg->basename
1337 lvo += 4;
1339 if (cfg->modtype == MCC || cfg->modtype == MUI || cfg->modtype == MCP)
1341 lvo++;
1342 fprintf(out,
1343 " &AROS_SLIB_ENTRY(MCC_Query,%s,%d),\n",
1344 cfg->basename, lvo
1347 else if (cfg->modtype == DATATYPE)
1349 lvo++;
1350 fprintf(out,
1351 " &AROS_SLIB_ENTRY(ObtainEngine,%s,%d),\n",
1352 cfg->basename, lvo
1356 else /* NORESIDENT */
1358 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
1360 int neednull = 0;
1361 struct functionhead *funclistit2;
1363 if (funclistit->lvo != 1)
1365 fprintf(stderr, "Module without a generated resident structure has to provide the Open function (LVO==1)\n");
1366 exit(20);
1368 else
1369 funclistit = funclistit->next;
1371 if (funclistit->lvo != 2)
1373 fprintf(stderr, "Module without a generated resident structure has to provide the Close function (LVO==2)\n");
1374 exit(20);
1376 else
1377 funclistit = funclistit->next;
1379 if (funclistit->lvo == 3)
1380 funclistit = funclistit->next;
1381 else
1382 neednull = 1;
1384 if (funclistit->lvo == 4)
1385 funclistit = funclistit->next;
1386 else
1387 neednull = 1;
1389 if (neednull)
1390 fprintf(out,
1391 "\n"
1392 "AROS_UFH1S(int, %s_null,\n"
1393 " AROS_UFHA(struct Library *, libbase, A6)\n"
1394 ")\n"
1395 "{\n"
1396 " AROS_USERFUNC_INIT\n"
1397 " return 0;\n"
1398 " AROS_USERFUNC_EXIT\n"
1399 "}\n",
1400 cfg->modulename
1403 funclistit = cfg->funclist;
1404 funclistit2 = funclistit->next;
1405 fprintf(out,
1406 "\n"
1407 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1408 "{\n"
1409 " &AROS_SLIB_ENTRY(%s,%s,%d),\n"
1410 " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1411 funclistit->internalname, cfg->basename, lvo+1,
1412 funclistit2->internalname, cfg->basename, lvo+2
1414 lvo += 2;
1415 funclistit = funclistit2->next;
1417 if (funclistit->lvo == 3)
1419 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1420 funclistit->internalname, cfg->basename, lvo+1
1422 funclistit = funclistit->next;
1424 else
1425 fprintf(out, " &%s_null,\n", cfg->modulename);
1426 lvo++;
1428 if (funclistit->lvo == 4)
1430 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1431 funclistit->internalname, cfg->basename, lvo+1
1433 funclistit = funclistit->next;
1435 else
1436 fprintf(out, " &%s_null,\n", cfg->modulename);
1437 lvo++;
1439 else
1441 fprintf(out,
1442 "\n"
1443 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1444 "{\n");
1448 while (funclistit != NULL)
1450 for (i = lvo+1; i<funclistit->lvo; i++)
1451 fprintf(out, " NULL,\n");
1452 lvo = funclistit->lvo;
1454 switch (funclistit->libcall)
1456 case STACK:
1457 fprintf(out, " &%s%s,\n", funclistit->internalname,
1458 cfg->options & OPTION_DUPBASE ? "_stub" : ""
1460 break;
1462 case REGISTER:
1463 case REGISTERMACRO:
1464 if (funclistit->version != lastversion) {
1465 lastversion = funclistit->version;
1466 fprintf(out, " /* Version %d */\n", lastversion);
1468 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n", funclistit->internalname, cfg->basename, lvo);
1469 break;
1471 default:
1472 fprintf(stderr, "Internal error: unhandled libcall type in writestart\n");
1473 exit(20);
1474 break;
1477 funclistit = funclistit->next;
1480 fprintf(out, " (void *)-1\n};\n");
1484 static void writesets(FILE *out, struct config *cfg)
1486 fprintf(out,
1487 "DEFINESET(INIT)\n"
1488 "DEFINESET(EXIT)\n"
1489 "DEFINESET(CTORS)\n"
1490 "DEFINESET(DTORS)\n"
1492 if (cfg->modtype != HANDLER)
1493 fprintf(out,
1494 "DEFINESET(INITLIB)\n"
1495 "DEFINESET(EXPUNGELIB)\n"
1497 if (!(cfg->options & OPTION_NOOPENCLOSE))
1498 fprintf(out,
1499 "DEFINESET(OPENLIB)\n"
1500 "DEFINESET(CLOSELIB)\n"
1502 if (cfg->modtype == DEVICE)
1503 fprintf(out,
1504 "DEFINESET(OPENDEV)\n"
1505 "DEFINESET(CLOSEDEV)\n"
1507 if (cfg->classlist != NULL)
1508 fprintf(out,
1509 "DEFINESET(CLASSESINIT)\n"
1510 "DEFINESET(CLASSESEXPUNGE)\n"
1512 fprintf(out, "\n");