2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
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
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
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
)
78 char line
[256], *banner
;
81 snprintf(line
, 255, "%s/%s_start.c", cfg
->gendir
, cfg
->modulename
);
82 out
= fopen(line
, "w");
90 banner
= getBanner(cfg
);
91 fprintf(out
, "%s", banner
);
95 "/* For comments and explanation of generated code look in writestart.c source code\n"
96 " of the genmodule program */\n"
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
);
119 if (cfg
->modtype
!= HANDLER
)
120 writefunctable(out
, cfg
);
122 for (cl
= cfg
->classlist
; cl
!= NULL
; cl
= cl
->next
)
124 switch (cl
->classtype
)
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
);
138 writeclassinit(out
, cl
);
141 writeoopinit(out
, cl
);
144 fprintf(stdout
, "Internal error: unsupported classtype in writestart\n");
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
;
162 if (cfg
->modtype
== DEVICE
)
165 "#include <exec/io.h>\n"
166 "#include <exec/errors.h>\n"
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"
178 "#include \"%s_libdefs.h\"\n"
184 "#include <proto/exec.h>\n"
185 "#include <proto/alib.h>\n"
187 "struct ExecBase *SysBase = NULL;\n"
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
)
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"
209 if (cfg
->options
& OPTION_DUPBASE
)
212 "#ifndef GM_ROOTBASE_FIELD\n"
213 "static LIBBASETYPEPTR GM_UNIQUENAME(rootbase);\n"
214 "#define GM_ROOTBASE_FIELD(lh) (GM_UNIQUENAME(rootbase))\n"
216 "static int __baseslot;\n"
217 "LIBBASETYPEPTR __GM_GetBase(void)\n"
219 " return (LIBBASETYPEPTR)SysBase->ThisTask->tc_UnionETask.tc_TaskStorage[__baseslot];\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"
235 "AROS_MAKE_ALIAS(__GM_GetBase, __comp_get_relbase);\n"
237 "static __used void __GM_SetBase(LIBBASETYPEPTR base)\n"
239 " SysBase->ThisTask->tc_UnionETask.tc_TaskStorage[__baseslot] = (IPTR)base;\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"
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"
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"
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"
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 */
305 "# error unsupported CPU type\n"
307 "struct __GM_DupBase {\n"
308 " LIBBASETYPE base;\n"
309 " LIBBASETYPEPTR oldbase;\n"
311 if (cfg
->options
& OPTION_PERTASKBASE
)
314 " ULONG taskopencount;\n"
315 " struct Task *task;\n"
317 " LIBBASETYPEPTR oldpertaskbase;\n"
322 "#define LIBBASESIZE sizeof(struct __GM_DupBase)\n"
324 if (cfg
->options
& OPTION_PERTASKBASE
)
327 "static int __pertaskslot;\n"
328 "LIBBASETYPEPTR __GM_GetBaseParent(LIBBASETYPEPTR base)\n"
330 " return ((struct __GM_DupBase *)base)->oldpertaskbase;\n"
332 "static inline LIBBASETYPEPTR __GM_GetPerTaskBase(void)\n"
334 " return (LIBBASETYPEPTR)SysBase->ThisTask->tc_UnionETask.tc_TaskStorage[__pertaskslot];\n"
336 "static inline void __GM_SetPerTaskBase(LIBBASETYPEPTR base)\n"
338 " SysBase->ThisTask->tc_UnionETask.tc_TaskStorage[__pertaskslot] = (IPTR)base;\n"
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
)
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"
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
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
389 if (classlistit
->classptr_var
== NULL
)
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"
397 classlistit
->basename
,
398 classlistit
->basename
,
399 classlistit
->basename
, classlistit
->basename
,
400 classlistit
->basename
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
);
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
)
435 writemuiincludes(out
);
438 /* Fall through: also write boopsi includes */
445 writeboopsiincludes(out
);
452 writeoopincludes(out
);
457 fprintf(stderr
, "Internal error: unhandled classtype in writedecl\n");
464 static void writedeclsets(FILE *out
, struct config
*cfg
)
467 "THIS_PROGRAM_HANDLES_SYMBOLSETS\n"
470 "DECLARESET(CTORS)\n"
471 "DECLARESET(DTORS)\n"
472 "DECLARESET(INITLIB)\n"
473 "DECLARESET(EXPUNGELIB)\n"
475 if (!(cfg
->options
& OPTION_NOOPENCLOSE
))
477 "DECLARESET(OPENLIB)\n"
478 "DECLARESET(CLOSELIB)\n"
480 if (cfg
->modtype
== DEVICE
)
482 "DECLARESET(OPENDEV)\n"
483 "DECLARESET(CLOSEDEV)\n"
485 if (cfg
->classlist
!= NULL
)
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"
496 static void writeresident(FILE *out
, struct config
*cfg
)
498 char *rt_skip
= cfg
->addromtag
;
501 fprintf(out
, "extern const struct Resident %s;\n", rt_skip
);
504 rt_skip
= "GM_UNIQUENAME(End)";
505 fprintf(out
, "extern const int %s;\n", rt_skip
);
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");
514 "extern const char GM_UNIQUENAME(LibName)[];\n"
515 "extern const char GM_UNIQUENAME(LibID)[];\n"
516 "extern const char GM_UNIQUENAME(Copyright)[];\n"
520 if (cfg
->options
& OPTION_RESAUTOINIT
)
523 "#define __freebase(lh)\\\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"
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"
542 if (cfg
->modtype
!= RESOURCE
&& cfg
->modtype
!= HANDLER
)
545 "AROS_LD1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
546 " AROS_LDA(LIBBASETYPEPTR, extralh, D0),\n"
547 " LIBBASETYPEPTR, lh, 3, %s\n"
554 "struct Resident const GM_UNIQUENAME(ROMTag) =\n"
557 " (struct Resident *)&GM_UNIQUENAME(ROMTag),\n"
560 " VERSION_NUMBER,\n",
563 switch (cfg
->modtype
)
573 fprintf(out
, " NT_LIBRARY,\n");
576 fprintf(out
, " NT_DEVICE,\n");
580 fprintf(out
, " NT_RESOURCE,\n");
583 fprintf(stderr
, "Internal error: unsupported modtype for NT_...\n");
589 " (CONST_STRPTR)&GM_UNIQUENAME(LibName)[0],\n"
590 " (CONST_STRPTR)&GM_UNIQUENAME(LibID)[6],\n"
592 if (cfg
->options
& OPTION_RESAUTOINIT
)
595 " (APTR)&GM_UNIQUENAME(InitTable)\n"
598 "static struct InitTable\n"
601 " const APTR *FuncTable;\n"
602 " struct DataTable *DataTable;\n"
603 " APTR InitLibTable;\n"
605 "const GM_UNIQUENAME(InitTable) =\n"
608 " &GM_UNIQUENAME(FuncTable)[0],\n"
610 " (APTR)GM_UNIQUENAME(InitLib)\n"
615 fprintf(out
, " (APTR)GM_UNIQUENAME(InitLib)\n};\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"
626 static void writehandler(FILE *out
, struct config
*cfg
)
629 struct handlerinfo
*hl
;
633 "#include <resources/filesysres.h>\n"
634 "#include <aros/system.h>\n"
635 "#include <proto/arossupport.h>\n"
636 "#include <proto/dos.h>\n"
640 for (hl
= cfg
->handlerlist
; hl
!= NULL
; hl
= hl
->next
) {
642 "extern void %s(void);\n",
648 "void GM_UNIQUENAME(InitHandler)(void)\n"
650 " struct FileSysResource *fsr;\n"
655 " BYTE autodetect;\n"
657 " ULONG stacksize;\n"
658 " void (*handler)(void);\n"
659 " } const __handler[] = { \n");
660 for (hl
= cfg
->handlerlist
; hl
!= NULL
; hl
= hl
->next
)
664 case HANDLER_RESIDENT
:
666 " { .id = 0, .name = AROS_CONST_BSTR(\"%s\"), .handler = %s }, \n",
667 hl
->name
, hl
->handler
);
669 case HANDLER_DOSTYPE
:
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
);
678 " BPTR seg[sizeof(__handler)/sizeof(__handler[0])] = { };\n"
680 " fsr = (struct FileSysResource *)OpenResource(\"FileSystem.resource\");\n"
681 " if (fsr == NULL)\n"
684 " for (i = 0; i < sizeof(__handler)/sizeof(__handler[0]); i++) {\n"
685 " struct FileSysEntry *fse;\n"
688 " /* Check to see if we can allocate the memory for the fse */\n"
689 " fse = AllocMem(sizeof(*fse), MEMF_CLEAR);\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"
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"
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"
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"
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"
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"
729 " Enqueue(&fsr->fsr_FileSysEntries, (struct Node *)fse);\n"
735 static void writeinitlib(FILE *out
, struct config
*cfg
)
737 if (cfg
->handlerlist
)
738 writehandler(out
, cfg
);
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"
747 " AROS_USERFUNC_INIT\n"
751 if (cfg
->modtype
!= HANDLER
)
753 " int initcalled = 0;\n"
759 if (cfg
->options
& OPTION_RESAUTOINIT
) {
762 " SysBase = sysBase;\n"
764 "#ifdef GM_SYSBASE_FIELD\n"
765 " GM_SYSBASE_FIELD(lh) = (APTR)sysBase;\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"
775 if (cfg
->modtype
!= HANDLER
)
777 if (!(cfg
->options
& OPTION_RESAUTOINIT
))
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"
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
))
800 " ((struct Library*)lh)->lib_NegSize = vecsize;\n"
801 " ((struct Library*)lh)->lib_PosSize = sizeof(LIBBASETYPE);\n"
809 " ((struct Library *)lh)->lib_Revision = REVISION_NUMBER;\n"
814 if (cfg
->options
& OPTION_DUPBASE
)
816 " __baseslot = AllocTaskStorageSlot();\n"
817 " __GM_SetBase(lh);\n"
819 if (cfg
->options
& OPTION_PERTASKBASE
)
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) && ");
834 "set_call_funcs(SETNAME(INIT), 1, 1) )\n"
836 " set_call_funcs(SETNAME(CTORS), -1, 0);\n"
840 if (cfg
->modtype
== HANDLER
)
846 " ok = set_call_libfuncs(SETNAME(INITLIB), 1, 1, lh);\n");
856 if (cfg
->modtype
!= HANDLER
)
859 " set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 0, lh);\n");
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
)
883 " FreeMem(mem, vecsize+LIBBASESIZE);\n"
894 if (!(cfg
->options
& OPTION_RESAUTOINIT
) && !(cfg
->options
& OPTION_SELFINIT
))
896 switch (cfg
->modtype
)
899 fprintf(out
, " AddResource(lh);\n");
903 fprintf(out
, " AddDevice(lh);\n");
906 /* Bare handlers don't require adding at all */
910 /* Everything else is library */
911 fprintf(out
, " AddLibrary(lh);\n");
916 if (cfg
->handlerlist
)
917 fprintf(out
, " GM_UNIQUENAME(InitHandler)();\n");
923 " AROS_USERFUNC_EXIT\n"
929 static void writeopenlib(FILE *out
, struct config
*cfg
)
931 switch (cfg
->modtype
)
934 fprintf(stderr
, "Internal error: writeopenlib called for a resource\n");
937 fprintf(stderr
, "Internal error: writeopenlib called for a handler\n");
940 if (cfg
->options
& OPTION_NOOPENCLOSE
)
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"
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"
963 " AROS_LIBFUNC_INIT\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"
969 " ((struct Library *)lh)->lib_OpenCnt++;\n"
970 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
972 " ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;\n"
976 " if (ioreq->io_Error >= 0)\n"
977 " ioreq->io_Error = IOERR_OPENFAIL;\n"
982 " AROS_LIBFUNC_EXIT\n"
989 if (cfg
->options
& OPTION_NOOPENCLOSE
)
992 "AROS_LD1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
993 " AROS_LDA (ULONG, version, D0),\n"
994 " LIBBASETYPEPTR, lh, 1, %s\n"
1001 "AROS_LH1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
1002 " AROS_LHA (ULONG, version, D0),\n"
1003 " LIBBASETYPEPTR, lh, 1, %s\n"
1006 " AROS_LIBFUNC_INIT\n"
1010 if (!(cfg
->options
& OPTION_DUPBASE
))
1013 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, lh) )\n"
1015 " ((struct Library *)lh)->lib_OpenCnt++;\n"
1016 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
1023 " AROS_LIBFUNC_EXIT\n"
1028 else /* OPTION_DUPBASE */
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
)
1037 " struct Task *thistask = FindTask(NULL);\n"
1038 " LIBBASETYPEPTR oldpertaskbase = __GM_GetPerTaskBase();\n"
1039 " newlib = (struct Library *)oldpertaskbase;\n"
1042 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1043 " if (dupbase->task != thistask)\n"
1045 " else if (thistask->tc_Node.ln_Type == NT_PROCESS\n"
1046 " && dupbase->retaddr != ((struct Process *)thistask)->pr_ReturnAddr\n"
1050 " dupbase->taskopencount++;\n"
1056 " if (newlib == NULL)\n"
1058 " newlib = MakeLibrary(GM_UNIQUENAME(InitTable).FuncTable,\n"
1059 " GM_UNIQUENAME(InitTable).DataTable,\n"
1061 " GM_UNIQUENAME(InitTable).Size,\n"
1064 " if (newlib == NULL)\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
)
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"
1083 " if (!(set_open_rellibraries(newlib)\n"
1084 " && set_call_libfuncs(SETNAME(OPENLIB), 1, 1, newlib)\n"
1088 if (cfg
->options
& OPTION_PERTASKBASE
)
1090 " __GM_SetPerTaskBase(oldpertaskbase);\n");
1092 " __freebase(newlib);\n"
1096 " ((struct Library *)lh)->lib_OpenCnt++;\n"
1097 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
1100 " return (LIBBASETYPEPTR)newlib;\n"
1102 " AROS_LIBFUNC_EXIT\n"
1111 static void writecloselib(FILE *out
, struct config
*cfg
)
1113 if (cfg
->options
& OPTION_NOOPENCLOSE
)
1115 if (cfg
->modtype
!= DEVICE
)
1117 "AROS_LD0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1118 " LIBBASETYPEPTR, lh, 2, %s\n"
1124 "AROS_LD1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1125 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1126 " LIBBASETYPEPTR, lh, 2, %s\n"
1132 if (cfg
->modtype
!= DEVICE
)
1134 "AROS_LH0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1135 " LIBBASETYPEPTR, lh, 2, %s\n"
1141 "AROS_LH1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1142 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1143 " LIBBASETYPEPTR, lh, 2, %s\n"
1150 " AROS_LIBFUNC_INIT\n"
1153 if (cfg
->modtype
== DEVICE
)
1155 " if (!set_call_devfuncs(SETNAME(CLOSEDEV), -1, 1, lh, ioreq, 0, 0))\n"
1160 if (!(cfg
->options
& OPTION_DUPBASE
))
1163 " ((struct Library *)lh)->lib_OpenCnt--;\n"
1164 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, lh);\n"
1167 else /* OPTION_DUPBASE */
1170 " LIBBASETYPEPTR rootbase = GM_ROOTBASE_FIELD(lh);\n"
1171 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)lh;\n"
1173 if (cfg
->options
& OPTION_PERTASKBASE
)
1175 " dupbase->taskopencount--;\n"
1176 " if (dupbase->taskopencount != 0)\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
)
1187 " __GM_SetPerTaskBase(((struct __GM_DupBase *)lh)->oldpertaskbase);\n"
1190 " __freebase(lh);\n"
1192 " ((struct Library *)lh)->lib_OpenCnt--;\n"
1196 if (!(cfg
->options
& OPTION_NOEXPUNGE
))
1200 " (((struct Library *)lh)->lib_OpenCnt == 0)\n"
1201 " && (((struct Library *)lh)->lib_Flags & LIBF_DELEXP)\n"
1204 " return AROS_LC1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1205 " AROS_LCA(LIBBASETYPEPTR, lh, D0),\n"
1206 " LIBBASETYPEPTR, lh, 3, %s\n"
1215 " AROS_LIBFUNC_EXIT\n"
1222 static void writeexpungelib(FILE *out
, struct config
*cfg
)
1225 "AROS_LH1 (BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1226 " AROS_LHA(LIBBASETYPEPTR, extralh, D0),\n"
1227 " LIBBASETYPEPTR, lh, 3, %s\n"
1233 " AROS_LIBFUNC_INIT\n"
1236 if (!(cfg
->options
& OPTION_NOEXPUNGE
))
1240 " if ( ((struct Library *)lh)->lib_OpenCnt == 0 )\n"
1242 " BPTR seglist = GM_SEGLIST_FIELD(lh);\n"
1244 " if(!set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 1, lh))\n"
1246 " ((struct Library *)lh)->lib_Flags |= LIBF_DELEXP;\n"
1250 " Remove((struct Node *)lh);\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"
1263 if (cfg
->options
& OPTION_PERTASKBASE
)
1265 " FreeTaskStorageSlot(__pertaskslot);\n"
1266 " __pertaskslot = 0;\n"
1270 " __freebase(lh);\n"
1272 " return seglist;\n"
1275 " ((struct Library *)lh)->lib_Flags |= LIBF_DELEXP;\n"
1282 " AROS_LIBFUNC_EXIT\n"
1289 static void writeextfunclib(FILE *out
, struct config
*cfg
)
1292 "AROS_LH0 (LIBBASETYPEPTR, GM_UNIQUENAME(ExtFuncLib),\n"
1293 " LIBBASETYPEPTR, lh, 4, %s\n"
1296 " AROS_LIBFUNC_INIT\n"
1298 " AROS_LIBFUNC_EXIT\n"
1307 writefunctable(FILE *out
,
1311 struct functionhead
*funclistit
= cfg
->funclist
;
1312 struct functionarg
*arglistit
;
1316 int lastversion
= 0;
1318 /* lvo contains the number of functions already printed in the functable */
1321 if (!(cfg
->options
& OPTION_NORESIDENT
))
1325 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1328 if (cfg
->modtype
!= RESOURCE
&& cfg
->modtype
!= HANDLER
)
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
1339 if (cfg
->modtype
== MCC
|| cfg
->modtype
== MUI
|| cfg
->modtype
== MCP
)
1343 " &AROS_SLIB_ENTRY(MCC_Query,%s,%d),\n",
1347 else if (cfg
->modtype
== DATATYPE
)
1351 " &AROS_SLIB_ENTRY(ObtainEngine,%s,%d),\n",
1356 else /* NORESIDENT */
1358 if (cfg
->modtype
!= RESOURCE
&& cfg
->modtype
!= HANDLER
)
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");
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");
1377 funclistit
= funclistit
->next
;
1379 if (funclistit
->lvo
== 3)
1380 funclistit
= funclistit
->next
;
1384 if (funclistit
->lvo
== 4)
1385 funclistit
= funclistit
->next
;
1392 "AROS_UFH1S(int, %s_null,\n"
1393 " AROS_UFHA(struct Library *, libbase, A6)\n"
1396 " AROS_USERFUNC_INIT\n"
1398 " AROS_USERFUNC_EXIT\n"
1403 funclistit
= cfg
->funclist
;
1404 funclistit2
= funclistit
->next
;
1407 "const APTR GM_UNIQUENAME(FuncTable)[]=\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
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
;
1425 fprintf(out
, " &%s_null,\n", cfg
->modulename
);
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
;
1436 fprintf(out
, " &%s_null,\n", cfg
->modulename
);
1443 "const APTR GM_UNIQUENAME(FuncTable)[]=\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
)
1457 fprintf(out
, " &%s%s,\n", funclistit
->internalname
,
1458 cfg
->options
& OPTION_DUPBASE
? "_stub" : ""
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
);
1472 fprintf(stderr
, "Internal error: unhandled libcall type in writestart\n");
1477 funclistit
= funclistit
->next
;
1480 fprintf(out
, " (void *)-1\n};\n");
1484 static void writesets(FILE *out
, struct config
*cfg
)
1489 "DEFINESET(CTORS)\n"
1490 "DEFINESET(DTORS)\n"
1492 if (cfg
->modtype
!= HANDLER
)
1494 "DEFINESET(INITLIB)\n"
1495 "DEFINESET(EXPUNGELIB)\n"
1497 if (!(cfg
->options
& OPTION_NOOPENCLOSE
))
1499 "DEFINESET(OPENLIB)\n"
1500 "DEFINESET(CLOSELIB)\n"
1502 if (cfg
->modtype
== DEVICE
)
1504 "DEFINESET(OPENDEV)\n"
1505 "DEFINESET(CLOSEDEV)\n"
1507 if (cfg
->classlist
!= NULL
)
1509 "DEFINESET(CLASSESINIT)\n"
1510 "DEFINESET(CLASSESEXPUNGE)\n"