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 void writestart(struct config
*cfg
)
29 char line
[256], *banner
;
32 snprintf(line
, 255, "%s/%s_start.c", cfg
->gendir
, cfg
->modulename
);
33 out
= fopen(line
, "w");
41 banner
= getBanner(cfg
);
42 fprintf(out
, "%s", banner
);
46 if (!(cfg
->options
& OPTION_NORESIDENT
))
48 writeresident(out
, cfg
);
49 writedeclsets(out
, cfg
);
50 writeinitlib(out
, cfg
);
51 if (cfg
->modtype
!= RESOURCE
&& cfg
->modtype
!= HANDLER
)
53 writeopenlib(out
, cfg
);
54 writecloselib(out
, cfg
);
55 writeexpungelib(out
, cfg
);
56 writeextfunclib(out
, cfg
);
57 if (cfg
->modtype
== MCC
|| cfg
->modtype
== MUI
|| cfg
->modtype
== MCP
)
58 writemccquery(out
, cfg
);
59 else if (cfg
->modtype
== DATATYPE
)
60 writeobtainengine(out
, cfg
);
65 if (cfg
->modtype
!= HANDLER
)
66 writefunctable(out
, cfg
);
68 for (cl
= cfg
->classlist
; cl
!= NULL
; cl
= cl
->next
)
70 switch (cl
->classtype
)
75 /* Second argument to next call: the class is not the main class if it is not
76 * the first class or the modtype is not a MUI class
78 writemccinit(out
, cl
!= cfg
->classlist
|| cfg
->modtype
!= cl
->classtype
, cl
);
84 writeclassinit(out
, cl
);
87 writeoopinit(out
, cl
);
90 fprintf(stdout
, "Internal error: unsupported classtype in writestart\n");
99 static void writedecl(FILE *out
, struct config
*cfg
)
101 struct stringlist
*linelistit
;
102 int boopsiinc
=0, muiinc
=0, oopinc
=0;
103 struct functionhead
*funclistit
;
104 struct functionarg
*arglistit
;
105 struct classinfo
*classlistit
;
108 if (cfg
->modtype
== DEVICE
)
111 "#include <exec/io.h>\n"
112 "#include <exec/errors.h>\n"
116 "#include <exec/types.h>\n"
117 "#include <exec/libraries.h>\n"
118 "#include <exec/resident.h>\n"
119 "#include <aros/libcall.h>\n"
120 "#include <aros/asmcall.h>\n"
121 "#include <aros/symbolsets.h>\n"
122 "#include <dos/dos.h>\n"
124 "#include \"%s_libdefs.h\"\n"
130 "#include <proto/exec.h>\n"
131 "#include <proto/alib.h>\n"
133 "struct ExecBase *SysBase = NULL;\n"
139 /* Write out declaration section provided in the config file */
140 for (linelistit
= cfg
->cdeflines
; linelistit
!= NULL
; linelistit
= linelistit
->next
)
142 fprintf(out
, "%s\n", linelistit
->s
);
145 /* Is there a variable for storing the segList ? */
146 if (!(cfg
->options
& OPTION_NOEXPUNGE
) && cfg
->modtype
!=RESOURCE
&& cfg
->modtype
!= HANDLER
)
149 "#ifndef GM_SEGLIST_FIELD\n"
150 "static BPTR __attribute__((unused)) GM_UNIQUENAME(seglist);\n"
151 "#define GM_SEGLIST_FIELD(lh) (GM_UNIQUENAME(seglist))\n"
155 if (cfg
->options
& OPTION_DUPBASE
)
157 "#ifndef GM_ROOTBASE_FIELD\n"
158 "static LIBBASETYPEPTR GM_UNIQUENAME(rootbase);\n"
159 "#define GM_ROOTBASE_FIELD(lh) (GM_UNIQUENAME(rootbase))\n"
161 "static int __baseslot;\n"
162 "LIBBASETYPEPTR __GM_GetBase(void)\n"
164 " return (LIBBASETYPEPTR)SysBase->ThisTask->tc_UnionETask.tc_TaskStorage[__baseslot];\n"
166 /* On AMD64 don't clobber registers used for argument passing,
167 * only clobber rax, r10 and r11
169 "#if defined __x86_64__\n"
170 "asm(\".global __comp_get_relbase\\n\"\n"
171 " \"__comp_get_relbase :\\n\"\n"
172 " \"\\tmovq SysBase(%%rip), %%rax\\n\"\n"
173 " \"\\tmovq 552(%%rax), %%rax\\n\"\n"
174 " \"\\tmovq 56(%%rax), %%r10\\n\"\n"
175 " \"\\tmovslq __baseslot(%%rip),%%r11\\n\"\n"
176 " \"\\tmovq (%%r10,%%r11,8), %%rax\\n\"\n"
180 "AROS_MAKE_ALIAS(__GM_GetBase, __comp_get_relbase);\n"
182 "static __used void __GM_SetBase(LIBBASETYPEPTR base)\n"
184 " SysBase->ThisTask->tc_UnionETask.tc_TaskStorage[__baseslot] = (IPTR)base;\n"
186 "#if defined __i386__\n"
187 "#define GM_INTERNALFUNCSTUB(fname)\\\n"
188 " asm(#fname \"_stub :\\n\"\\\n"
189 " \"\\tpushl %%edx\\n\"\\\n"
190 " \"\\tcall __GM_SetBase\\n\"\\\n"
191 " \"\\tpopl %%edx\\n\"\\\n"
192 " \"\\tjmp \" #fname \"\\n\"\\\n"
194 "#elif defined __x86_64__\n"
195 /* On AMD64 we can't call __GM_SetBase() as it will mess
196 * up with the parameters passed in registers
198 "#define GM_INTERNALFUNCSTUB(fname)\\\n"
199 /* On x86_64 we can use r10 and r11 in between function call and entry
200 r11 contains libbase */
201 " asm(#fname \"_stub :\\n\"\\\n"
202 " \"\\tpushq %%rax\\n\"\\\n"
203 " \"\\tmovq SysBase(%%rip), %%rax\\n\"\\\n"
204 " \"\\tmovslq __baseslot(%%rip),%%r10\\n\"\\\n"
205 " \"\\tmovq 552(%%rax), %%rax\\n\"\\\n"
206 " \"\\tmovq 56(%%rax), %%rax\\n\"\\\n"
207 " \"\\tmovq %%r11,(%%rax,%%r10,8)\\n\"\\\n"
208 " \"\\tpopq %%rax\\n\"\\\n"
209 " \"\\tjmp \" #fname \"\\n\"\\\n"
211 "#elif defined __mc68000__\n"
212 "#define GM_INTERNALFUNCSTUB(fname)\\\n"
213 " asm(#fname \"_stub :\\n\"\\\n"
214 " \"\\tmove.l %%a1,%%sp@-\\n\"\\\n"
215 " \"\\tjsr __GM_SetBase\\n\"\\\n"
216 " \"\\tmove.l %%sp@+,%%a1\\n\"\\\n"
217 " \"\\tjmp \" #fname \"\\n\"\\\n"
219 "#elif defined __powerpc__\n"
220 /* FIXME: struct offsets are from i386,
221 need to be checked ! */
222 "#define GM_INTERNALFUNCSTUB(fname)\\\n"
223 /* On PPC we can use r0, r11, r12 in between function call and entry
224 * r12 contains libbase
226 " asm(#fname \"_stub :\\n\"\\\n"
227 /* r0 = SysBase->ThisTask->tc_UnionETask.tc_TaskStorage */
228 " \"\\tlis 11, SysBase@ha\\n\"\\\n"
229 " \"\\tlwz 11, SysBase@l(11)\\n\"\\\n"
230 " \"\\tlwz 11, 284(11)\\n\"\\\n"
231 " \"\\tlwz 0, 36(11)\\n\"\\\n"
232 /* r11 = r0 + __baseslot */
233 " \"\\tlis 11, __baseslot@ha\\n\"\\\n"
234 " \"\\tlwz 11, __baseslot@l(11)\\n\"\\\n"
235 " \"\\tadd 11,0,11\\n\"\\\n"
236 /* *r11 = r12 (== libbase) */
237 " \"\\tstw 12, 0(11)\\n\"\\\n"
238 " \"\\tb \" #fname \"\\n\"\\\n"
240 "#elif defined __arm__\n"
241 "#define GM_INTERNALFUNCSTUB(fname)\\\n"
242 " asm(#fname \"_stub :\\n\"\\\n"
243 " \"\\tpush {r0, r1, r2, r3, lr}\\n\"\\\n"
244 " \"\\tmov r0, r12\\n\"\\\n"
245 " \"\\tbl __GM_SetBase\\n\"\\\n" /* r12 may be scratched */
246 " \"\\tpop {r0, r1, r2, r3, lr}\\n\"\\\n"
247 " \"\\tb \" #fname \"\\n\"\\\n" /* call function */
250 "# error unsupported CPU type\n"
254 if (cfg
->options
& OPTION_PERTASKBASE
)
256 "struct __GM_PerTaskBase {\n"
257 " LIBBASETYPE base;\n"
258 " ULONG taskopencount;\n"
259 " struct Task *task;\n"
261 " LIBBASETYPEPTR oldbase;\n"
263 "#define LIBBASESIZE sizeof(struct __GM_PerTaskBase)\n"
264 "static int __pertaskslot;\n"
265 "LIBBASETYPEPTR __GM_GetBaseParent(LIBBASETYPEPTR base)\n"
267 " return ((struct __GM_PerTaskBase *)base)->oldbase;\n"
269 "static inline LIBBASETYPEPTR __GM_GetPerTaskBase(void)\n"
271 " return (LIBBASETYPEPTR)SysBase->ThisTask->tc_UnionETask.tc_TaskStorage[__pertaskslot];\n"
273 "static inline void __GM_SetPerTaskBase(LIBBASETYPEPTR base)\n"
275 " SysBase->ThisTask->tc_UnionETask.tc_TaskStorage[__pertaskslot] = (IPTR)base;\n"
279 fprintf(out
, "#define LIBBASESIZE sizeof(LIBBASETYPE)\n");
281 for (classlistit
= cfg
->classlist
; classlistit
!= NULL
; classlistit
= classlistit
->next
)
283 /* For the main class basename is the same as the module basename */
284 if (strcmp(classlistit
->basename
, cfg
->basename
) == 0)
286 if (classlistit
->classptr_var
== NULL
)
289 "#if !defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
290 "static APTR GM_UNIQUENAME(%sClass);\n"
291 "#define GM_CLASSPTR_FIELD(lh) (GM_UNIQUENAME(%sClass))\n"
292 "#define %s_CLASSPTR_FIELD(lh) (GM_UNIQUENAME(%sClass))\n"
293 "#define %s_STORE_CLASSPTR 1\n"
294 "#elif defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
295 "#define %s_CLASSPTR_FIELD(lh) (GM_CLASSPTR_FIELD(lh))\n"
296 "#elif !defined(GM_CLASSPTR_FIELD) && defined(%s_CLASSPTR_FIELD)\n"
297 "#define GM_CLASSPTR_FIELD(lh) (%s_CLASSPTR_FIELD(lh))\n"
299 classlistit
->basename
,
300 classlistit
->basename
,
301 classlistit
->basename
,
302 classlistit
->basename
, classlistit
->basename
,
303 classlistit
->basename
,
304 classlistit
->basename
,
305 classlistit
->basename
,
306 classlistit
->basename
,
307 classlistit
->basename
313 "#define GM_CLASSPTR_FIELD(lh) (%s)\n"
314 "#define %s_CLASSPTR_FIELD(lh) (%s)\n"
315 "#define %s_STORE_CLASSPTR 1\n",
316 classlistit
->classptr_var
,
317 classlistit
->basename
, classlistit
->classptr_var
,
318 classlistit
->basename
324 if (classlistit
->classptr_var
== NULL
)
327 "#if !defined(%s_CLASSPTR_FIELD)\n"
328 "static APTR GM_UNIQUENAME(%sClass);\n"
329 "#define %s_CLASSPTR_FIELD(lh) (GM_UNIQUENAME(%sClass))\n"
330 "#define %s_STORE_CLASSPTR 1\n"
332 classlistit
->basename
,
333 classlistit
->basename
,
334 classlistit
->basename
, classlistit
->basename
,
335 classlistit
->basename
341 "#define %s_CLASSPTR_FIELD(lh) (%s)\n"
342 "#define %s_STORE_CLASSPTR 1\n",
343 classlistit
->basename
, classlistit
->classptr_var
,
344 classlistit
->basename
350 /* Write out the defines for the functions of the function table */
351 writefuncdefs(out
, cfg
, cfg
->funclist
);
352 /* Write internal stubs */
353 writefuncinternalstubs(out
, cfg
, cfg
->funclist
);
357 /* Write out the includes needed for the classes */
358 if (cfg
->classlist
!= NULL
)
359 writeboopsiincludes(out
);
361 for (classlistit
= cfg
->classlist
; classlistit
!= NULL
; classlistit
= classlistit
->next
)
363 switch (classlistit
->classtype
)
370 writemuiincludes(out
);
373 /* Fall through: also write boopsi includes */
380 writeboopsiincludes(out
);
387 writeoopincludes(out
);
392 fprintf(stderr
, "Internal error: unhandled classtype in writedecl\n");
399 static void writedeclsets(FILE *out
, struct config
*cfg
)
402 "THIS_PROGRAM_HANDLES_SYMBOLSETS\n"
405 "DECLARESET(CTORS)\n"
406 "DECLARESET(DTORS)\n"
407 "DECLARESET(INITLIB)\n"
408 "DECLARESET(EXPUNGELIB)\n"
410 if (!(cfg
->options
& OPTION_NOOPENCLOSE
))
412 "DECLARESET(OPENLIB)\n"
413 "DECLARESET(CLOSELIB)\n"
415 if (cfg
->modtype
== DEVICE
)
417 "DECLARESET(OPENDEV)\n"
418 "DECLARESET(CLOSEDEV)\n"
420 if (cfg
->classlist
!= NULL
)
422 "DECLARESET(CLASSESINIT)\n"
423 "DECLARESET(CLASSESEXPUNGE)\n"
424 "#define ADD2INITCLASSES(symbol, pri) ADD2SET(symbol, classesinit, pri)\n"
425 "#define ADD2EXPUNGECLASSES(symbol, pri) ADD2SET(symbol, classesexpunge, pri)\n"
431 static void writeresident(FILE *out
, struct config
*cfg
)
433 char *rt_skip
= cfg
->addromtag
;
436 fprintf(out
, "extern const struct Resident %s;\n", rt_skip
);
439 rt_skip
= "GM_UNIQUENAME(End)";
440 fprintf(out
, "extern const int %s;\n", rt_skip
);
443 "extern const APTR GM_UNIQUENAME(FuncTable)[];\n"
445 if (cfg
->options
& OPTION_RESAUTOINIT
)
446 fprintf(out
, "static const struct InitTable GM_UNIQUENAME(InitTable);\n");
449 "extern const char GM_UNIQUENAME(LibName)[];\n"
450 "extern const char GM_UNIQUENAME(LibID)[];\n"
451 "extern const char GM_UNIQUENAME(Copyright)[];\n"
455 if (cfg
->options
& OPTION_RESAUTOINIT
)
458 "#define __freebase(lh)\\\n"
460 " UWORD negsize, possize;\\\n"
461 " UBYTE *negptr = (UBYTE *)lh;\\\n"
462 " negsize = ((struct Library *)lh)->lib_NegSize;\\\n"
463 " negptr -= negsize;\\\n"
464 " possize = ((struct Library *)lh)->lib_PosSize;\\\n"
465 " FreeMem (negptr, negsize+possize);\\\n"
471 "AROS_UFP3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
472 " AROS_UFPA(LIBBASETYPEPTR, lh, D0),\n"
473 " AROS_UFPA(BPTR, segList, A0),\n"
474 " AROS_UFPA(struct ExecBase *, sysBase, A6)\n"
477 if (cfg
->modtype
!= RESOURCE
&& cfg
->modtype
!= HANDLER
)
480 "AROS_LD1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
481 " AROS_LDA(LIBBASETYPEPTR, extralh, D0),\n"
482 " LIBBASETYPEPTR, lh, 3, %s\n"
489 "struct Resident const GM_UNIQUENAME(ROMTag) =\n"
492 " (struct Resident *)&GM_UNIQUENAME(ROMTag),\n"
495 " VERSION_NUMBER,\n",
498 switch (cfg
->modtype
)
508 fprintf(out
, " NT_LIBRARY,\n");
511 fprintf(out
, " NT_DEVICE,\n");
515 fprintf(out
, " NT_RESOURCE,\n");
518 fprintf(stderr
, "Internal error: unsupported modtype for NT_...\n");
524 " (CONST_STRPTR)&GM_UNIQUENAME(LibName)[0],\n"
525 " (CONST_STRPTR)&GM_UNIQUENAME(LibID)[6],\n"
527 if (cfg
->options
& OPTION_RESAUTOINIT
)
530 " (APTR)&GM_UNIQUENAME(InitTable)\n"
533 "static struct InitTable\n"
536 " const APTR *FuncTable;\n"
537 " struct DataTable *DataTable;\n"
538 " APTR InitLibTable;\n"
540 "const GM_UNIQUENAME(InitTable) =\n"
543 " &GM_UNIQUENAME(FuncTable)[0],\n"
545 " (APTR)GM_UNIQUENAME(InitLib)\n"
550 fprintf(out
, " (APTR)GM_UNIQUENAME(InitLib)\n};\n");
554 "const char GM_UNIQUENAME(LibName)[] = MOD_NAME_STRING;\n"
555 "const char GM_UNIQUENAME(LibID)[] = VERSION_STRING;\n"
556 "const char GM_UNIQUENAME(Copyright)[] = COPYRIGHT_STRING;\n"
561 static void writehandler(FILE *out
, struct config
*cfg
)
564 struct handlerinfo
*hl
;
568 "#include <resources/filesysres.h>\n"
569 "#include <aros/system.h>\n"
570 "#include <proto/arossupport.h>\n"
571 "#include <proto/dos.h>\n"
575 for (hl
= cfg
->handlerlist
; hl
!= NULL
; hl
= hl
->next
) {
577 "extern void %s(void);\n",
583 "void GM_UNIQUENAME(InitHandler)(void)\n"
585 " struct FileSysResource *fsr;\n"
590 " BYTE autodetect;\n"
592 " ULONG stacksize;\n"
593 " void (*handler)(void);\n"
594 " } const __handler[] = { \n");
595 for (hl
= cfg
->handlerlist
; hl
!= NULL
; hl
= hl
->next
)
599 case HANDLER_RESIDENT
:
601 " { .id = 0, .name = AROS_CONST_BSTR(\"%s\"), .handler = %s }, \n",
602 hl
->name
, hl
->handler
);
604 case HANDLER_DOSTYPE
:
606 " { .id = 0x%08x, .name = AROS_CONST_BSTR(MOD_NAME_STRING), .handler = %s, .autodetect = %d, .priority = %d, .stacksize = %d*sizeof(IPTR) }, \n",
607 hl
->id
, hl
->handler
, hl
->autodetect
, hl
->priority
, hl
->stacksize
);
613 " BPTR seg[sizeof(__handler)/sizeof(__handler[0])] = { };\n"
615 " fsr = (struct FileSysResource *)OpenResource(\"FileSystem.resource\");\n"
616 " if (fsr == NULL)\n"
619 " for (i = 0; i < sizeof(__handler)/sizeof(__handler[0]); i++) {\n"
620 " struct FileSysEntry *fse;\n"
623 " /* Check to see if we can allocate the memory for the fse */\n"
624 " fse = AllocMem(sizeof(*fse), MEMF_CLEAR);\n"
628 " /* Did we already make a segment for this handler? */\n"
629 " for (j = 0; j < i; j++)\n"
630 " if (__handler[i].handler == __handler[j].handler)\n"
632 " if (seg[j] == (BPTR)0)\n"
633 " seg[j] = CreateSegList(__handler[j].handler);\n"
634 " if (seg[j] == BNULL) {\n"
635 " FreeMem(fse, sizeof(*fse));\n"
639 " /* DOS ID based handlers\n"
640 " * NOTE: fse_DosType == 0 is a special flag use in\n"
641 " * dos.library's init to add the handler to the\n"
642 " * resident segment list\n"
644 " fse->fse_Node.ln_Name = VERSION_STRING;\n"
645 " fse->fse_Node.ln_Pri = __handler[i].autodetect;\n"
646 " fse->fse_DosType = __handler[i].id;\n"
647 " fse->fse_Version = (MAJOR_VERSION << 16) | MINOR_VERSION;\n"
648 " fse->fse_PatchFlags = FSEF_SEGLIST | FSEF_GLOBALVEC | FSEF_HANDLER | FSEF_PRIORITY;\n"
649 " if (__handler[i].stacksize) {\n"
650 " fse->fse_PatchFlags |= FSEF_STACKSIZE;\n"
651 " fse->fse_StackSize = __handler[i].stacksize;\n"
653 " fse->fse_Handler = __handler[i].name;\n"
654 " fse->fse_Priority = __handler[i].priority;\n"
655 " fse->fse_SegList = seg[j];\n"
656 " fse->fse_GlobalVec = (BPTR)(SIPTR)-1;\n"
658 " /* Add to the list. I know forbid and permit are\n"
659 " * a little unnecessary for the pre-multitasking state\n"
660 " * we should be in at this point, but you never know\n"
661 " * who's going to blindly copy this code as an example.\n"
664 " Enqueue(&fsr->fsr_FileSysEntries, (struct Node *)fse);\n"
670 static void writeinitlib(FILE *out
, struct config
*cfg
)
672 if (cfg
->handlerlist
)
673 writehandler(out
, cfg
);
676 "AROS_UFH3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
677 " AROS_UFHA(LIBBASETYPEPTR, lh, D0),\n"
678 " AROS_UFHA(BPTR, segList, A0),\n"
679 " AROS_UFHA(struct ExecBase *, sysBase, A6)\n"
682 " AROS_USERFUNC_INIT\n"
686 if (cfg
->modtype
!= HANDLER
)
688 " int initcalled = 0;\n"
694 if (cfg
->options
& OPTION_RESAUTOINIT
) {
697 " SysBase = sysBase;\n"
699 "#ifdef GM_SYSBASE_FIELD\n"
700 " GM_SYSBASE_FIELD(lh) = (APTR)sysBase;\n"
702 "#ifdef GM_OOPBASE_FIELD\n"
703 " GM_OOPBASE_FIELD(lh) = OpenLibrary(\"oop.library\",0);\n"
704 " if (GM_OOPBASE_FIELD(lh) == NULL)\n"
710 if (cfg
->modtype
!= HANDLER
)
712 if (!(cfg
->options
& OPTION_RESAUTOINIT
))
719 " vecsize = FUNCTIONS_COUNT * LIB_VECTSIZE;\n"
720 " if (vecsize > 0)\n"
721 " vecsize = ((vecsize-1)/sizeof(IPTR) + 1)*sizeof(IPTR);\n"
722 " mem = AllocMem(vecsize+sizeof(LIBBASETYPE), MEMF_PUBLIC|MEMF_CLEAR);\n"
723 " if (mem == NULL)\n"
725 " lh = (LIBBASETYPEPTR)(mem + vecsize);\n"
726 " n = (struct Node *)lh;\n"
727 " n->ln_Type = NT_RESOURCE;\n"
728 " n->ln_Pri = RESIDENTPRI;\n"
729 " n->ln_Name = (char *)GM_UNIQUENAME(LibName);\n"
730 " MakeFunctions(lh, (APTR)GM_UNIQUENAME(FuncTable), NULL);\n"
732 if ((cfg
->modtype
!= RESOURCE
) && (cfg
->options
& OPTION_SELFINIT
))
735 " ((struct Library*)lh)->lib_NegSize = vecsize;\n"
736 " ((struct Library*)lh)->lib_PosSize = sizeof(LIBBASETYPE);\n"
744 " ((struct Library *)lh)->lib_Revision = REVISION_NUMBER;\n"
749 if (cfg
->options
& OPTION_DUPBASE
)
751 " __baseslot = AllocTaskStorageSlot();\n"
752 " __GM_SetBase(lh);\n"
754 if (cfg
->options
& OPTION_PERTASKBASE
)
756 " __pertaskslot = AllocTaskStorageSlot();\n"
759 if (!(cfg
->options
& OPTION_NOEXPUNGE
) && cfg
->modtype
!=RESOURCE
&& cfg
->modtype
!= HANDLER
)
760 fprintf(out
, " GM_SEGLIST_FIELD(lh) = segList;\n");
761 if (cfg
->options
& OPTION_DUPBASE
)
762 fprintf(out
, " GM_ROOTBASE_FIELD(lh) = (LIBBASETYPEPTR)lh;\n");
763 fprintf(out
, " if (");
764 if (!(cfg
->options
& OPTION_NOAUTOLIB
))
765 fprintf(out
, "set_open_libraries() && ");
766 if (cfg
->classlist
!= NULL
)
767 fprintf(out
, "set_call_libfuncs(SETNAME(CLASSESINIT), 1, 1, lh) && ");
769 "set_call_funcs(SETNAME(INIT), 1, 1) )\n"
771 " set_call_funcs(SETNAME(CTORS), -1, 0);\n"
775 if (cfg
->modtype
== HANDLER
)
781 " ok = set_call_libfuncs(SETNAME(INITLIB), 1, 1, lh);\n");
791 if (cfg
->modtype
!= HANDLER
)
794 " set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 0, lh);\n");
797 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
798 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
800 if (cfg
->classlist
!= NULL
)
801 fprintf(out
, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, lh);\n");
802 if (!(cfg
->options
& OPTION_NOAUTOLIB
))
803 fprintf(out
, " set_close_libraries();\n");
805 if (cfg
->modtype
!= HANDLER
)
807 if (cfg
->options
& OPTION_RESAUTOINIT
)
818 " FreeMem(mem, vecsize+LIBBASESIZE);\n"
829 if (!(cfg
->options
& OPTION_RESAUTOINIT
) && !(cfg
->options
& OPTION_SELFINIT
))
831 switch (cfg
->modtype
)
834 fprintf(out
, " AddResource(lh);\n");
838 fprintf(out
, " AddDevice(lh);\n");
841 /* Bare handlers don't require adding at all */
845 /* Everything else is library */
846 fprintf(out
, " AddLibrary(lh);\n");
851 if (cfg
->handlerlist
)
852 fprintf(out
, " GM_UNIQUENAME(InitHandler)();\n");
858 " AROS_USERFUNC_EXIT\n"
864 static void writeopenlib(FILE *out
, struct config
*cfg
)
866 switch (cfg
->modtype
)
869 fprintf(stderr
, "Internal error: writeopenlib called for a resource\n");
872 fprintf(stderr
, "Internal error: writeopenlib called for a handler\n");
875 if (cfg
->options
& OPTION_NOOPENCLOSE
)
877 "AROS_LD3 (void, GM_UNIQUENAME(OpenLib),\n"
878 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
879 " AROS_LDA(ULONG, unitnum, D0),\n"
880 " AROS_LDA(ULONG, flags, D1),\n"
881 " LIBBASETYPEPTR, lh, 1, %s\n"
888 "AROS_LH3 (void, GM_UNIQUENAME(OpenLib),\n"
889 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
890 " AROS_LHA(IPTR, unitnum, D0),\n"
891 " AROS_LHA(ULONG, flags, D1),\n"
892 " LIBBASETYPEPTR, lh, 1, %s\n"
898 " AROS_LIBFUNC_INIT\n"
900 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, lh)\n"
901 " && set_call_devfuncs(SETNAME(OPENDEV), 1, 1, lh, ioreq, unitnum, flags)\n"
904 " ((struct Library *)lh)->lib_OpenCnt++;\n"
905 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
907 " ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;\n"
911 " if (ioreq->io_Error >= 0)\n"
912 " ioreq->io_Error = IOERR_OPENFAIL;\n"
917 " AROS_LIBFUNC_EXIT\n"
924 if (cfg
->options
& OPTION_NOOPENCLOSE
)
927 "AROS_LD1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
928 " AROS_LDA (ULONG, version, D0),\n"
929 " LIBBASETYPEPTR, lh, 1, %s\n"
936 "AROS_LH1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
937 " AROS_LHA (ULONG, version, D0),\n"
938 " LIBBASETYPEPTR, lh, 1, %s\n"
941 " AROS_LIBFUNC_INIT\n"
945 if (!(cfg
->options
& OPTION_DUPBASE
))
948 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, lh) )\n"
950 " ((struct Library *)lh)->lib_OpenCnt++;\n"
951 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
958 " AROS_LIBFUNC_EXIT\n"
963 else /* OPTION_DUPBASE */
966 " struct Library *newlib = NULL;\n"
967 " UWORD possize = ((struct Library *)lh)->lib_PosSize;\n"
969 if (cfg
->options
& OPTION_PERTASKBASE
)
971 " struct Task *thistask = FindTask(NULL);\n"
972 " LIBBASETYPEPTR oldbase = __GM_GetPerTaskBase();\n"
973 " newlib = (struct Library *)oldbase;\n"
976 " struct __GM_PerTaskBase *pertaskbase = (struct __GM_PerTaskBase *)newlib;\n"
977 " if (pertaskbase->task != thistask)\n"
979 " else if (thistask->tc_Node.ln_Type == NT_PROCESS\n"
980 " && pertaskbase->retaddr != ((struct Process *)thistask)->pr_ReturnAddr\n"
984 " pertaskbase->taskopencount++;\n"
990 " if (newlib == NULL)\n"
992 " newlib = MakeLibrary(GM_UNIQUENAME(InitTable).FuncTable,\n"
993 " GM_UNIQUENAME(InitTable).DataTable,\n"
995 " GM_UNIQUENAME(InitTable).Size,\n"
998 " if (newlib == NULL)\n"
1001 " CopyMem(lh, newlib, possize);\n"
1002 " __GM_SetBase((LIBBASETYPEPTR)newlib);\n"
1004 if (cfg
->options
& OPTION_PERTASKBASE
)
1006 " struct __GM_PerTaskBase *pertaskbase = (struct __GM_PerTaskBase *)newlib;\n"
1007 " pertaskbase->task = thistask;\n"
1008 " if (thistask->tc_Node.ln_Type == NT_PROCESS)\n"
1009 " pertaskbase->retaddr = ((struct Process *)thistask)->pr_ReturnAddr;\n"
1010 " pertaskbase->oldbase = oldbase;\n"
1011 " pertaskbase->taskopencount = 1;\n"
1012 " __GM_SetPerTaskBase((LIBBASETYPEPTR)newlib);\n"
1016 " if (!(set_open_rellibraries(newlib)\n"
1017 " && set_call_libfuncs(SETNAME(OPENLIB), 1, 1, newlib)\n"
1021 if (cfg
->options
& OPTION_PERTASKBASE
)
1023 " __GM_SetPerTaskBase(oldbase);\n");
1025 " __freebase(newlib);\n"
1029 " ((struct Library *)lh)->lib_OpenCnt++;\n"
1030 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
1033 " return (LIBBASETYPEPTR)newlib;\n"
1035 " AROS_LIBFUNC_EXIT\n"
1044 static void writecloselib(FILE *out
, struct config
*cfg
)
1046 if (cfg
->options
& OPTION_NOOPENCLOSE
)
1048 if (cfg
->modtype
!= DEVICE
)
1050 "AROS_LD0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1051 " LIBBASETYPEPTR, lh, 2, %s\n"
1057 "AROS_LD1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1058 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1059 " LIBBASETYPEPTR, lh, 2, %s\n"
1065 if (cfg
->modtype
!= DEVICE
)
1067 "AROS_LH0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1068 " LIBBASETYPEPTR, lh, 2, %s\n"
1074 "AROS_LH1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1075 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1076 " LIBBASETYPEPTR, lh, 2, %s\n"
1083 " AROS_LIBFUNC_INIT\n"
1086 if (cfg
->modtype
== DEVICE
)
1088 " if (!set_call_devfuncs(SETNAME(CLOSEDEV), -1, 1, lh, ioreq, 0, 0))\n"
1093 if (!(cfg
->options
& OPTION_DUPBASE
))
1096 " ((struct Library *)lh)->lib_OpenCnt--;\n"
1097 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, lh);\n"
1103 " LIBBASETYPEPTR rootbase = GM_ROOTBASE_FIELD(lh);\n"
1105 if (cfg
->options
& OPTION_PERTASKBASE
)
1107 " struct __GM_PerTaskBase *pertaskbase = (struct __GM_PerTaskBase *)lh;\n"
1108 " pertaskbase->taskopencount--;\n"
1109 " if (pertaskbase->taskopencount != 0)\n"
1114 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, lh);\n"
1115 " set_close_rellibraries(lh);\n");
1116 if (cfg
->options
& OPTION_PERTASKBASE
)
1118 " __GM_SetPerTaskBase(((struct __GM_PerTaskBase *)lh)->oldbase);\n");
1120 " __freebase(lh);\n"
1122 " ((struct Library *)lh)->lib_OpenCnt--;\n"
1126 if (!(cfg
->options
& OPTION_NOEXPUNGE
))
1130 " (((struct Library *)lh)->lib_OpenCnt == 0)\n"
1131 " && (((struct Library *)lh)->lib_Flags & LIBF_DELEXP)\n"
1134 " return AROS_LC1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1135 " AROS_LCA(LIBBASETYPEPTR, lh, D0),\n"
1136 " LIBBASETYPEPTR, lh, 3, %s\n"
1145 " AROS_LIBFUNC_EXIT\n"
1152 static void writeexpungelib(FILE *out
, struct config
*cfg
)
1155 "AROS_LH1 (BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1156 " AROS_LHA(LIBBASETYPEPTR, extralh, D0),\n"
1157 " LIBBASETYPEPTR, lh, 3, %s\n"
1163 " AROS_LIBFUNC_INIT\n"
1166 if (!(cfg
->options
& OPTION_NOEXPUNGE
))
1170 " if ( ((struct Library *)lh)->lib_OpenCnt == 0 )\n"
1172 " BPTR seglist = GM_SEGLIST_FIELD(lh);\n"
1174 " if(!set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 1, lh))\n"
1176 " ((struct Library *)lh)->lib_Flags |= LIBF_DELEXP;\n"
1180 " Remove((struct Node *)lh);\n"
1182 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
1183 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
1185 if (cfg
->classlist
!= NULL
)
1186 fprintf(out
, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, lh);\n");
1187 if (!(cfg
->options
& OPTION_NOAUTOLIB
))
1188 fprintf(out
, " set_close_libraries();\n"
1189 "#ifdef GM_OOPBASE_FIELD\n"
1190 " CloseLibrary((struct Library *)GM_OOPBASE_FIELD(lh));\n"
1193 if (cfg
->options
& OPTION_PERTASKBASE
)
1195 " FreeTaskStorageSlot(__pertaskslot);\n"
1196 " __pertaskslot = 0;\n"
1200 " __freebase(lh);\n"
1202 " return seglist;\n"
1205 " ((struct Library *)lh)->lib_Flags |= LIBF_DELEXP;\n"
1212 " AROS_LIBFUNC_EXIT\n"
1219 static void writeextfunclib(FILE *out
, struct config
*cfg
)
1222 "AROS_LH0 (LIBBASETYPEPTR, GM_UNIQUENAME(ExtFuncLib),\n"
1223 " LIBBASETYPEPTR, lh, 4, %s\n"
1226 " AROS_LIBFUNC_INIT\n"
1228 " AROS_LIBFUNC_EXIT\n"
1237 writefunctable(FILE *out
,
1241 struct functionhead
*funclistit
= cfg
->funclist
;
1242 struct functionarg
*arglistit
;
1246 int lastversion
= 0;
1248 /* lvo contains the number of functions already printed in the functable */
1251 if (!(cfg
->options
& OPTION_NORESIDENT
))
1255 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1258 if (cfg
->modtype
!= RESOURCE
&& cfg
->modtype
!= HANDLER
)
1261 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(OpenLib),%s,1),\n"
1262 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(CloseLib),%s,2),\n"
1263 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExpungeLib),%s,3),\n"
1264 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExtFuncLib),%s,4),\n",
1265 cfg
->basename
, cfg
->basename
, cfg
->basename
, cfg
->basename
1269 if (cfg
->modtype
== MCC
|| cfg
->modtype
== MUI
|| cfg
->modtype
== MCP
)
1273 " &AROS_SLIB_ENTRY(MCC_Query,%s,%d),\n",
1277 else if (cfg
->modtype
== DATATYPE
)
1281 " &AROS_SLIB_ENTRY(ObtainEngine,%s,%d),\n",
1286 else /* NORESIDENT */
1288 if (cfg
->modtype
!= RESOURCE
&& cfg
->modtype
!= HANDLER
)
1291 struct functionhead
*funclistit2
;
1293 if (funclistit
->lvo
!= 1)
1295 fprintf(stderr
, "Module without a generated resident structure has to provide the Open function (LVO==1)\n");
1299 funclistit
= funclistit
->next
;
1301 if (funclistit
->lvo
!= 2)
1303 fprintf(stderr
, "Module without a generated resident structure has to provide the Close function (LVO==2)\n");
1307 funclistit
= funclistit
->next
;
1309 if (funclistit
->lvo
== 3)
1310 funclistit
= funclistit
->next
;
1314 if (funclistit
->lvo
== 4)
1315 funclistit
= funclistit
->next
;
1322 "AROS_UFH1S(int, %s_null,\n"
1323 " AROS_UFHA(struct Library *, libbase, A6)\n"
1326 " AROS_USERFUNC_INIT\n"
1328 " AROS_USERFUNC_EXIT\n"
1333 funclistit
= cfg
->funclist
;
1334 funclistit2
= funclistit
->next
;
1337 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1339 " &AROS_SLIB_ENTRY(%s,%s,%d),\n"
1340 " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1341 funclistit
->internalname
, cfg
->basename
, lvo
+1,
1342 funclistit2
->internalname
, cfg
->basename
, lvo
+2
1345 funclistit
= funclistit2
->next
;
1347 if (funclistit
->lvo
== 3)
1349 fprintf(out
, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1350 funclistit
->internalname
, cfg
->basename
, lvo
+1
1352 funclistit
= funclistit
->next
;
1355 fprintf(out
, " &%s_null,\n", cfg
->modulename
);
1358 if (funclistit
->lvo
== 4)
1360 fprintf(out
, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1361 funclistit
->internalname
, cfg
->basename
, lvo
+1
1363 funclistit
= funclistit
->next
;
1366 fprintf(out
, " &%s_null,\n", cfg
->modulename
);
1373 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1378 while (funclistit
!= NULL
)
1380 for (i
= lvo
+1; i
<funclistit
->lvo
; i
++)
1381 fprintf(out
, " NULL,\n");
1382 lvo
= funclistit
->lvo
;
1384 switch (funclistit
->libcall
)
1387 fprintf(out
, " &%s%s,\n", funclistit
->internalname
,
1388 cfg
->options
& OPTION_DUPBASE
? "_stub" : ""
1394 if (funclistit
->version
!= lastversion
) {
1395 lastversion
= funclistit
->version
;
1396 fprintf(out
, " /* Version %d */\n", lastversion
);
1398 fprintf(out
, " &AROS_SLIB_ENTRY(%s,%s,%d),\n", funclistit
->internalname
, cfg
->basename
, lvo
);
1402 fprintf(stderr
, "Internal error: unhandled libcall type in writestart\n");
1407 funclistit
= funclistit
->next
;
1410 fprintf(out
, " (void *)-1\n};\n");
1414 static void writesets(FILE *out
, struct config
*cfg
)
1419 "DEFINESET(CTORS)\n"
1420 "DEFINESET(DTORS)\n"
1422 if (cfg
->modtype
!= HANDLER
)
1424 "DEFINESET(INITLIB)\n"
1425 "DEFINESET(EXPUNGELIB)\n"
1427 if (!(cfg
->options
& OPTION_NOOPENCLOSE
))
1429 "DEFINESET(OPENLIB)\n"
1430 "DEFINESET(CLOSELIB)\n"
1432 if (cfg
->modtype
== DEVICE
)
1434 "DEFINESET(OPENDEV)\n"
1435 "DEFINESET(CLOSEDEV)\n"
1437 if (cfg
->classlist
!= NULL
)
1439 "DEFINESET(CLASSESINIT)\n"
1440 "DEFINESET(CLASSESEXPUNGE)\n"