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 "LONG __GM_BaseSlot;\n"
217 /* If AROS_GM_GETBASE is defined, then it is a
218 * macro that generates the __GM_GetBase() function
219 * in assembly. See include/aros/x86_64/cpu.h for
220 * an example implementation.
222 "#ifdef AROS_GM_GETBASE\n"
223 "extern void *__GM_GetBase(void);\n"
224 "AROS_GM_GETBASE()\n"
225 "static inline void *__GM_GetBase_Safe(void)\n"
227 " return (LIBBASETYPEPTR)GetTaskStorageSlot(__GM_BaseSlot);\n"
230 "void *__GM_GetBase(void)\n"
232 " return (void *)GetTaskStorageSlot(__GM_BaseSlot);\n"
234 "#define __GM_GetBase_Safe() __GM_GetBase()\n"
236 "static inline BOOL __GM_SetBase_Safe(LIBBASETYPEPTR base)\n"
238 " return SetTaskStorageSlot(__GM_BaseSlot, (IPTR)base);\n"
240 "struct __GM_DupBase {\n"
241 " LIBBASETYPE base;\n"
242 " LIBBASETYPEPTR oldbase;\n"
244 if (cfg
->options
& OPTION_PERTASKBASE
)
247 " ULONG taskopencount;\n"
248 " struct Task *task;\n"
250 " LIBBASETYPEPTR oldpertaskbase;\n"
256 " struct Library *relbase[%d];\n"
257 , slist_length(cfg
->relbases
)
262 "#define LIBBASESIZE sizeof(struct __GM_DupBase)\n"
266 struct stringlist
*sl
;
269 for (sl
=cfg
->relbases
, i
= 0; sl
; sl
=sl
->next
, i
++) {
271 "const IPTR %s_offset = offsetof(struct __GM_DupBase, relbase[%d]);\n"
277 if (cfg
->options
& OPTION_PERTASKBASE
)
280 "static LONG __pertaskslot;\n"
281 "LIBBASETYPEPTR __GM_GetBaseParent(LIBBASETYPEPTR base)\n"
283 " return ((struct __GM_DupBase *)base)->oldpertaskbase;\n"
285 "static inline LIBBASETYPEPTR __GM_GetPerTaskBase(void)\n"
287 " return (LIBBASETYPEPTR)GetTaskStorageSlot(__pertaskslot);\n"
289 "static inline void __GM_SetPerTaskBase(LIBBASETYPEPTR base)\n"
291 " SetTaskStorageSlot(__pertaskslot, (IPTR)base);\n"
297 struct stringlist
*sl
;
299 for (sl
= cfg
->relbases
; sl
; sl
= sl
->next
)
302 "AROS_IMPORT_ASM_SYM(void *,__%s,__aros_rellib_%s);\n"
310 fprintf(out
, "#define LIBBASESIZE sizeof(LIBBASETYPE)\n");
312 for (classlistit
= cfg
->classlist
; classlistit
!= NULL
; classlistit
= classlistit
->next
)
314 /* For the main class basename is the same as the module basename */
315 if (strcmp(classlistit
->basename
, cfg
->basename
) == 0)
317 if (classlistit
->classptr_var
== NULL
)
320 "#if !defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
321 "static APTR GM_UNIQUENAME(%sClass);\n"
322 "#define GM_CLASSPTR_FIELD(lh) (GM_UNIQUENAME(%sClass))\n"
323 "#define %s_CLASSPTR_FIELD(lh) (GM_UNIQUENAME(%sClass))\n"
324 "#define %s_STORE_CLASSPTR 1\n"
325 "#elif defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
326 "#define %s_CLASSPTR_FIELD(lh) (GM_CLASSPTR_FIELD(lh))\n"
327 "#elif !defined(GM_CLASSPTR_FIELD) && defined(%s_CLASSPTR_FIELD)\n"
328 "#define GM_CLASSPTR_FIELD(lh) (%s_CLASSPTR_FIELD(lh))\n"
330 classlistit
->basename
,
331 classlistit
->basename
,
332 classlistit
->basename
,
333 classlistit
->basename
, classlistit
->basename
,
334 classlistit
->basename
,
335 classlistit
->basename
,
336 classlistit
->basename
,
337 classlistit
->basename
,
338 classlistit
->basename
344 "#define GM_CLASSPTR_FIELD(lh) (%s)\n"
345 "#define %s_CLASSPTR_FIELD(lh) (%s)\n"
346 "#define %s_STORE_CLASSPTR 1\n",
347 classlistit
->classptr_var
,
348 classlistit
->basename
, classlistit
->classptr_var
,
349 classlistit
->basename
355 if (classlistit
->classptr_var
== NULL
)
358 "#if !defined(%s_CLASSPTR_FIELD)\n"
359 "static APTR GM_UNIQUENAME(%sClass);\n"
360 "#define %s_CLASSPTR_FIELD(lh) (GM_UNIQUENAME(%sClass))\n"
361 "#define %s_STORE_CLASSPTR 1\n"
363 classlistit
->basename
,
364 classlistit
->basename
,
365 classlistit
->basename
, classlistit
->basename
,
366 classlistit
->basename
372 "#define %s_CLASSPTR_FIELD(lh) (%s)\n"
373 "#define %s_STORE_CLASSPTR 1\n",
374 classlistit
->basename
, classlistit
->classptr_var
,
375 classlistit
->basename
381 /* Write out the defines for the functions of the function table */
382 writefuncdefs(out
, cfg
, cfg
->funclist
);
386 /* Write out the includes needed for the classes */
387 if (cfg
->classlist
!= NULL
)
388 writeboopsiincludes(out
);
390 for (classlistit
= cfg
->classlist
; classlistit
!= NULL
; classlistit
= classlistit
->next
)
392 switch (classlistit
->classtype
)
399 writemuiincludes(out
);
402 /* Fall through: also write boopsi includes */
409 writeboopsiincludes(out
);
416 writeoopincludes(out
);
421 fprintf(stderr
, "Internal error: unhandled classtype in writedecl\n");
428 static void writedeclsets(FILE *out
, struct config
*cfg
)
431 "THIS_PROGRAM_HANDLES_SYMBOLSETS\n"
434 "DECLARESET(CTORS)\n"
435 "DECLARESET(DTORS)\n"
436 "DECLARESET(INITLIB)\n"
437 "DECLARESET(EXPUNGELIB)\n"
439 if (!(cfg
->options
& OPTION_NOOPENCLOSE
))
441 "DECLARESET(OPENLIB)\n"
442 "DECLARESET(CLOSELIB)\n"
444 if (cfg
->modtype
== DEVICE
)
446 "DECLARESET(OPENDEV)\n"
447 "DECLARESET(CLOSEDEV)\n"
449 if (cfg
->classlist
!= NULL
)
451 "DECLARESET(CLASSESINIT)\n"
452 "DECLARESET(CLASSESEXPUNGE)\n"
453 "#define ADD2INITCLASSES(symbol, pri) ADD2SET(symbol, classesinit, pri)\n"
454 "#define ADD2EXPUNGECLASSES(symbol, pri) ADD2SET(symbol, classesexpunge, pri)\n"
460 static void writeresident(FILE *out
, struct config
*cfg
)
462 char *rt_skip
= cfg
->addromtag
;
465 fprintf(out
, "extern const struct Resident %s;\n", rt_skip
);
468 rt_skip
= "GM_UNIQUENAME(End)";
469 fprintf(out
, "extern const int %s;\n", rt_skip
);
472 "extern const APTR GM_UNIQUENAME(FuncTable)[];\n"
474 if (cfg
->options
& OPTION_RESAUTOINIT
)
475 fprintf(out
, "static const struct InitTable GM_UNIQUENAME(InitTable);\n");
478 "extern const char GM_UNIQUENAME(LibName)[];\n"
479 "extern const char GM_UNIQUENAME(LibID)[];\n"
480 "extern const char GM_UNIQUENAME(Copyright)[];\n"
484 if (cfg
->options
& OPTION_RESAUTOINIT
)
487 "#define __freebase(lh)\\\n"
489 " UWORD negsize, possize;\\\n"
490 " UBYTE *negptr = (UBYTE *)lh;\\\n"
491 " negsize = ((struct Library *)lh)->lib_NegSize;\\\n"
492 " negptr -= negsize;\\\n"
493 " possize = ((struct Library *)lh)->lib_PosSize;\\\n"
494 " FreeMem (negptr, negsize+possize);\\\n"
500 "AROS_UFP3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
501 " AROS_UFPA(LIBBASETYPEPTR, lh, D0),\n"
502 " AROS_UFPA(BPTR, segList, A0),\n"
503 " AROS_UFPA(struct ExecBase *, sysBase, A6)\n"
506 if (cfg
->modtype
!= RESOURCE
&& cfg
->modtype
!= HANDLER
)
509 "AROS_LD1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
510 " AROS_LDA(LIBBASETYPEPTR, extralh, D0),\n"
511 " LIBBASETYPEPTR, lh, 3, %s\n"
518 "struct Resident const GM_UNIQUENAME(ROMTag) =\n"
521 " (struct Resident *)&GM_UNIQUENAME(ROMTag),\n"
524 " VERSION_NUMBER,\n",
527 switch (cfg
->modtype
)
537 fprintf(out
, " NT_LIBRARY,\n");
540 fprintf(out
, " NT_DEVICE,\n");
544 fprintf(out
, " NT_RESOURCE,\n");
547 fprintf(stderr
, "Internal error: unsupported modtype for NT_...\n");
553 " (CONST_STRPTR)&GM_UNIQUENAME(LibName)[0],\n"
554 " (CONST_STRPTR)&GM_UNIQUENAME(LibID)[6],\n"
556 if (cfg
->options
& OPTION_RESAUTOINIT
)
559 " (APTR)&GM_UNIQUENAME(InitTable)\n"
562 "static struct InitTable\n"
565 " const APTR *FuncTable;\n"
566 " struct DataTable *DataTable;\n"
567 " APTR InitLibTable;\n"
569 "const GM_UNIQUENAME(InitTable) =\n"
572 " &GM_UNIQUENAME(FuncTable)[0],\n"
574 " (APTR)GM_UNIQUENAME(InitLib)\n"
579 fprintf(out
, " (APTR)GM_UNIQUENAME(InitLib)\n};\n");
583 "const char GM_UNIQUENAME(LibName)[] = MOD_NAME_STRING;\n"
584 "const char GM_UNIQUENAME(LibID)[] = VERSION_STRING;\n"
585 "const char GM_UNIQUENAME(Copyright)[] = COPYRIGHT_STRING;\n"
590 static void writehandler(FILE *out
, struct config
*cfg
)
593 struct handlerinfo
*hl
;
597 "#include <resources/filesysres.h>\n"
598 "#include <aros/system.h>\n"
599 "#include <proto/arossupport.h>\n"
600 "#include <proto/dos.h>\n"
604 for (hl
= cfg
->handlerlist
; hl
!= NULL
; hl
= hl
->next
) {
606 "extern void %s(void);\n",
612 "void GM_UNIQUENAME(InitHandler)(void)\n"
614 " struct FileSysResource *fsr;\n"
619 " BYTE autodetect;\n"
621 " ULONG stacksize;\n"
622 " void (*handler)(void);\n"
623 " } const __handler[] = { \n");
624 for (hl
= cfg
->handlerlist
; hl
!= NULL
; hl
= hl
->next
)
628 case HANDLER_RESIDENT
:
630 " { .id = 0, .name = AROS_CONST_BSTR(\"%s\"), .handler = %s }, \n",
631 hl
->name
, hl
->handler
);
633 case HANDLER_DOSTYPE
:
635 " { .id = 0x%08x, .name = AROS_CONST_BSTR(MOD_NAME_STRING), .handler = %s, .autodetect = %d, .priority = %d, .stacksize = %d*sizeof(IPTR) }, \n",
636 hl
->id
, hl
->handler
, hl
->autodetect
, hl
->priority
, hl
->stacksize
);
642 " BPTR seg[sizeof(__handler)/sizeof(__handler[0])] = { };\n"
644 " fsr = (struct FileSysResource *)OpenResource(\"FileSystem.resource\");\n"
645 " if (fsr == NULL)\n"
648 " for (i = 0; i < sizeof(__handler)/sizeof(__handler[0]); i++) {\n"
649 " struct FileSysEntry *fse;\n"
652 " /* Check to see if we can allocate the memory for the fse */\n"
653 " fse = AllocMem(sizeof(*fse), MEMF_CLEAR);\n"
657 " /* Did we already make a segment for this handler? */\n"
658 " for (j = 0; j < i; j++)\n"
659 " if (__handler[i].handler == __handler[j].handler)\n"
661 " if (seg[j] == (BPTR)0)\n"
662 " seg[j] = CreateSegList(__handler[j].handler);\n"
663 " if (seg[j] == BNULL) {\n"
664 " FreeMem(fse, sizeof(*fse));\n"
668 " /* DOS ID based handlers\n"
669 " * NOTE: fse_DosType == 0 is a special flag use in\n"
670 " * dos.library's init to add the handler to the\n"
671 " * resident segment list\n"
673 " fse->fse_Node.ln_Name = VERSION_STRING;\n"
674 " fse->fse_Node.ln_Pri = __handler[i].autodetect;\n"
675 " fse->fse_DosType = __handler[i].id;\n"
676 " fse->fse_Version = (MAJOR_VERSION << 16) | MINOR_VERSION;\n"
677 " fse->fse_PatchFlags = FSEF_SEGLIST | FSEF_GLOBALVEC | FSEF_HANDLER | FSEF_PRIORITY;\n"
678 " if (__handler[i].stacksize) {\n"
679 " fse->fse_PatchFlags |= FSEF_STACKSIZE;\n"
680 " fse->fse_StackSize = __handler[i].stacksize;\n"
682 " fse->fse_Handler = __handler[i].name;\n"
683 " fse->fse_Priority = __handler[i].priority;\n"
684 " fse->fse_SegList = seg[j];\n"
685 " fse->fse_GlobalVec = (BPTR)(SIPTR)-1;\n"
687 " /* Add to the list. I know forbid and permit are\n"
688 " * a little unnecessary for the pre-multitasking state\n"
689 " * we should be in at this point, but you never know\n"
690 " * who's going to blindly copy this code as an example.\n"
693 " Enqueue(&fsr->fsr_FileSysEntries, (struct Node *)fse);\n"
699 static void writeinitlib(FILE *out
, struct config
*cfg
)
701 if (cfg
->handlerlist
)
702 writehandler(out
, cfg
);
705 "AROS_UFH3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
706 " AROS_UFHA(LIBBASETYPEPTR, lh, D0),\n"
707 " AROS_UFHA(BPTR, segList, A0),\n"
708 " AROS_UFHA(struct ExecBase *, sysBase, A6)\n"
711 " AROS_USERFUNC_INIT\n"
715 if (cfg
->modtype
!= HANDLER
)
717 " int initcalled = 0;\n"
723 if (cfg
->options
& OPTION_RESAUTOINIT
) {
726 " SysBase = sysBase;\n"
728 "#ifdef GM_SYSBASE_FIELD\n"
729 " GM_SYSBASE_FIELD(lh) = (APTR)sysBase;\n"
731 "#ifdef GM_OOPBASE_FIELD\n"
732 " GM_OOPBASE_FIELD(lh) = OpenLibrary(\"oop.library\",0);\n"
733 " if (GM_OOPBASE_FIELD(lh) == NULL)\n"
739 if (cfg
->modtype
!= HANDLER
)
741 if (!(cfg
->options
& OPTION_RESAUTOINIT
))
748 " vecsize = FUNCTIONS_COUNT * LIB_VECTSIZE;\n"
749 " if (vecsize > 0)\n"
750 " vecsize = ((vecsize-1)/sizeof(IPTR) + 1)*sizeof(IPTR);\n"
751 " mem = AllocMem(vecsize+sizeof(LIBBASETYPE), MEMF_PUBLIC|MEMF_CLEAR);\n"
752 " if (mem == NULL)\n"
754 " lh = (LIBBASETYPEPTR)(mem + vecsize);\n"
755 " n = (struct Node *)lh;\n"
756 " n->ln_Type = NT_RESOURCE;\n"
757 " n->ln_Pri = RESIDENTPRI;\n"
758 " n->ln_Name = (char *)GM_UNIQUENAME(LibName);\n"
759 " MakeFunctions(lh, (APTR)GM_UNIQUENAME(FuncTable), NULL);\n"
761 if ((cfg
->modtype
!= RESOURCE
) && (cfg
->options
& OPTION_SELFINIT
))
764 " ((struct Library*)lh)->lib_NegSize = vecsize;\n"
765 " ((struct Library*)lh)->lib_PosSize = sizeof(LIBBASETYPE);\n"
773 " ((struct Library *)lh)->lib_Revision = REVISION_NUMBER;\n"
778 if (cfg
->options
& OPTION_DUPBASE
)
780 " __GM_BaseSlot = AllocTaskStorageSlot();\n"
781 " if (!__GM_SetBase_Safe(lh)) {\n"
782 " FreeTaskStorageSlot(__GM_BaseSlot);\n"
786 if (cfg
->options
& OPTION_PERTASKBASE
)
788 " __pertaskslot = AllocTaskStorageSlot();\n"
791 if (!(cfg
->options
& OPTION_NOEXPUNGE
) && cfg
->modtype
!=RESOURCE
&& cfg
->modtype
!= HANDLER
)
792 fprintf(out
, " GM_SEGLIST_FIELD(lh) = segList;\n");
793 if (cfg
->options
& OPTION_DUPBASE
)
794 fprintf(out
, " GM_ROOTBASE_FIELD(lh) = (LIBBASETYPEPTR)lh;\n");
795 fprintf(out
, " if (");
796 if (!(cfg
->options
& OPTION_NOAUTOLIB
))
797 fprintf(out
, "set_open_libraries() && ");
798 if (cfg
->classlist
!= NULL
)
799 fprintf(out
, "set_call_libfuncs(SETNAME(CLASSESINIT), 1, 1, lh) && ");
801 "set_call_funcs(SETNAME(INIT), 1, 1) )\n"
803 " set_call_funcs(SETNAME(CTORS), -1, 0);\n"
807 if (cfg
->modtype
== HANDLER
)
813 " ok = set_call_libfuncs(SETNAME(INITLIB), 1, 1, lh);\n");
823 if (cfg
->modtype
!= HANDLER
)
826 " set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 0, lh);\n");
829 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
830 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
832 if (cfg
->classlist
!= NULL
)
833 fprintf(out
, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, lh);\n");
834 if (!(cfg
->options
& OPTION_NOAUTOLIB
))
835 fprintf(out
, " set_close_libraries();\n");
837 if (cfg
->modtype
!= HANDLER
)
839 if (cfg
->options
& OPTION_RESAUTOINIT
)
850 " FreeMem(mem, vecsize+LIBBASESIZE);\n"
861 if (!(cfg
->options
& OPTION_RESAUTOINIT
) && !(cfg
->options
& OPTION_SELFINIT
))
863 switch (cfg
->modtype
)
866 fprintf(out
, " AddResource(lh);\n");
870 fprintf(out
, " AddDevice(lh);\n");
873 /* Bare handlers don't require adding at all */
877 /* Everything else is library */
878 fprintf(out
, " AddLibrary(lh);\n");
883 if (cfg
->handlerlist
)
884 fprintf(out
, " GM_UNIQUENAME(InitHandler)();\n");
890 " AROS_USERFUNC_EXIT\n"
896 static void writeopenlib(FILE *out
, struct config
*cfg
)
898 switch (cfg
->modtype
)
901 fprintf(stderr
, "Internal error: writeopenlib called for a resource\n");
904 fprintf(stderr
, "Internal error: writeopenlib called for a handler\n");
907 if (cfg
->options
& OPTION_NOOPENCLOSE
)
909 "AROS_LD3 (void, GM_UNIQUENAME(OpenLib),\n"
910 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
911 " AROS_LDA(ULONG, unitnum, D0),\n"
912 " AROS_LDA(ULONG, flags, D1),\n"
913 " LIBBASETYPEPTR, lh, 1, %s\n"
920 "AROS_LH3 (void, GM_UNIQUENAME(OpenLib),\n"
921 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
922 " AROS_LHA(IPTR, unitnum, D0),\n"
923 " AROS_LHA(ULONG, flags, D1),\n"
924 " LIBBASETYPEPTR, lh, 1, %s\n"
930 " AROS_LIBFUNC_INIT\n"
932 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, lh)\n"
933 " && set_call_devfuncs(SETNAME(OPENDEV), 1, 1, lh, ioreq, unitnum, flags)\n"
936 " ((struct Library *)lh)->lib_OpenCnt++;\n"
937 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
939 " ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;\n"
943 " if (ioreq->io_Error >= 0)\n"
944 " ioreq->io_Error = IOERR_OPENFAIL;\n"
949 " AROS_LIBFUNC_EXIT\n"
956 if (cfg
->options
& OPTION_NOOPENCLOSE
)
959 "AROS_LD1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
960 " AROS_LDA (ULONG, version, D0),\n"
961 " LIBBASETYPEPTR, lh, 1, %s\n"
968 "AROS_LH1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
969 " AROS_LHA (ULONG, version, D0),\n"
970 " LIBBASETYPEPTR, lh, 1, %s\n"
973 " AROS_LIBFUNC_INIT\n"
977 if (!(cfg
->options
& OPTION_DUPBASE
))
980 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, lh) )\n"
982 " ((struct Library *)lh)->lib_OpenCnt++;\n"
983 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
990 " AROS_LIBFUNC_EXIT\n"
995 else /* OPTION_DUPBASE */
998 " struct Library *newlib = NULL;\n"
999 " UWORD possize = ((struct Library *)lh)->lib_PosSize;\n"
1000 " LIBBASETYPEPTR oldbase = __GM_GetBase_Safe();\n"
1002 if (cfg
->options
& OPTION_PERTASKBASE
)
1004 " struct Task *thistask = FindTask(NULL);\n"
1005 " LIBBASETYPEPTR oldpertaskbase = __GM_GetPerTaskBase();\n"
1006 " newlib = (struct Library *)oldpertaskbase;\n"
1009 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1010 " if (dupbase->task != thistask)\n"
1012 " else if (thistask->tc_Node.ln_Type == NT_PROCESS\n"
1013 " && dupbase->retaddr != ((struct Process *)thistask)->pr_ReturnAddr\n"
1017 " dupbase->taskopencount++;\n"
1023 " if (newlib == NULL)\n"
1025 " newlib = MakeLibrary(GM_UNIQUENAME(InitTable).FuncTable,\n"
1026 " GM_UNIQUENAME(InitTable).DataTable,\n"
1028 " GM_UNIQUENAME(InitTable).Size,\n"
1031 " if (newlib == NULL)\n"
1034 " CopyMem(lh, newlib, possize);\n"
1035 " __GM_SetBase_Safe((LIBBASETYPEPTR)newlib);\n"
1036 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1037 " dupbase->oldbase = oldbase;\n"
1039 if (cfg
->options
& OPTION_PERTASKBASE
)
1041 " dupbase->task = thistask;\n"
1042 " if (thistask->tc_Node.ln_Type == NT_PROCESS)\n"
1043 " dupbase->retaddr = ((struct Process *)thistask)->pr_ReturnAddr;\n"
1044 " dupbase->oldpertaskbase = oldpertaskbase;\n"
1045 " dupbase->taskopencount = 1;\n"
1046 " __GM_SetPerTaskBase((LIBBASETYPEPTR)newlib);\n"
1050 " if (!(set_open_rellibraries(newlib)\n"
1051 " && set_call_libfuncs(SETNAME(OPENLIB), 1, 1, newlib)\n"
1055 if (cfg
->options
& OPTION_PERTASKBASE
)
1057 " __GM_SetPerTaskBase(oldpertaskbase);\n");
1059 " __freebase(newlib);\n"
1063 " ((struct Library *)lh)->lib_OpenCnt++;\n"
1064 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
1067 " return (LIBBASETYPEPTR)newlib;\n"
1069 " AROS_LIBFUNC_EXIT\n"
1078 static void writecloselib(FILE *out
, struct config
*cfg
)
1080 if (cfg
->options
& OPTION_NOOPENCLOSE
)
1082 if (cfg
->modtype
!= DEVICE
)
1084 "AROS_LD0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1085 " LIBBASETYPEPTR, lh, 2, %s\n"
1091 "AROS_LD1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1092 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1093 " LIBBASETYPEPTR, lh, 2, %s\n"
1099 if (cfg
->modtype
!= DEVICE
)
1101 "AROS_LH0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1102 " LIBBASETYPEPTR, lh, 2, %s\n"
1108 "AROS_LH1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1109 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1110 " LIBBASETYPEPTR, lh, 2, %s\n"
1117 " AROS_LIBFUNC_INIT\n"
1120 if (cfg
->modtype
== DEVICE
)
1122 " if (!set_call_devfuncs(SETNAME(CLOSEDEV), -1, 1, lh, ioreq, 0, 0))\n"
1127 if (!(cfg
->options
& OPTION_DUPBASE
))
1130 " ((struct Library *)lh)->lib_OpenCnt--;\n"
1131 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, lh);\n"
1134 else /* OPTION_DUPBASE */
1137 " LIBBASETYPEPTR rootbase = GM_ROOTBASE_FIELD(lh);\n"
1138 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)lh;\n"
1140 if (cfg
->options
& OPTION_PERTASKBASE
)
1142 " dupbase->taskopencount--;\n"
1143 " if (dupbase->taskopencount != 0)\n"
1148 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, lh);\n"
1149 " set_close_rellibraries(lh);\n"
1150 " __GM_SetBase_Safe(dupbase->oldbase);\n"
1152 if (cfg
->options
& OPTION_PERTASKBASE
)
1154 " __GM_SetPerTaskBase(((struct __GM_DupBase *)lh)->oldpertaskbase);\n"
1157 " __freebase(lh);\n"
1159 " ((struct Library *)lh)->lib_OpenCnt--;\n"
1163 if (!(cfg
->options
& OPTION_NOEXPUNGE
))
1167 " (((struct Library *)lh)->lib_OpenCnt == 0)\n"
1168 " && (((struct Library *)lh)->lib_Flags & LIBF_DELEXP)\n"
1171 " return AROS_LC1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1172 " AROS_LCA(LIBBASETYPEPTR, lh, D0),\n"
1173 " LIBBASETYPEPTR, lh, 3, %s\n"
1182 " AROS_LIBFUNC_EXIT\n"
1189 static void writeexpungelib(FILE *out
, struct config
*cfg
)
1192 "AROS_LH1 (BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1193 " AROS_LHA(LIBBASETYPEPTR, extralh, D0),\n"
1194 " LIBBASETYPEPTR, lh, 3, %s\n"
1200 " AROS_LIBFUNC_INIT\n"
1203 if (!(cfg
->options
& OPTION_NOEXPUNGE
))
1207 " if ( ((struct Library *)lh)->lib_OpenCnt == 0 )\n"
1209 " BPTR seglist = GM_SEGLIST_FIELD(lh);\n"
1211 " if(!set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 1, lh))\n"
1213 " ((struct Library *)lh)->lib_Flags |= LIBF_DELEXP;\n"
1217 " Remove((struct Node *)lh);\n"
1219 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
1220 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
1222 if (cfg
->classlist
!= NULL
)
1223 fprintf(out
, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, lh);\n");
1224 if (!(cfg
->options
& OPTION_NOAUTOLIB
))
1225 fprintf(out
, " set_close_libraries();\n"
1226 "#ifdef GM_OOPBASE_FIELD\n"
1227 " CloseLibrary((struct Library *)GM_OOPBASE_FIELD(lh));\n"
1230 if (cfg
->options
& OPTION_PERTASKBASE
)
1232 " FreeTaskStorageSlot(__pertaskslot);\n"
1233 " __pertaskslot = 0;\n"
1237 " __freebase(lh);\n"
1239 " return seglist;\n"
1242 " ((struct Library *)lh)->lib_Flags |= LIBF_DELEXP;\n"
1249 " AROS_LIBFUNC_EXIT\n"
1256 static void writeextfunclib(FILE *out
, struct config
*cfg
)
1259 "AROS_LH0 (LIBBASETYPEPTR, GM_UNIQUENAME(ExtFuncLib),\n"
1260 " LIBBASETYPEPTR, lh, 4, %s\n"
1263 " AROS_LIBFUNC_INIT\n"
1265 " AROS_LIBFUNC_EXIT\n"
1274 writefunctable(FILE *out
,
1278 struct functionhead
*funclistit
= cfg
->funclist
;
1279 struct functionarg
*arglistit
;
1283 int lastversion
= 0;
1285 /* lvo contains the number of functions already printed in the functable */
1288 if (!(cfg
->options
& OPTION_NORESIDENT
))
1292 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1295 if (cfg
->modtype
!= RESOURCE
&& cfg
->modtype
!= HANDLER
)
1298 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(OpenLib),%s,1),\n"
1299 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(CloseLib),%s,2),\n"
1300 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExpungeLib),%s,3),\n"
1301 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExtFuncLib),%s,4),\n",
1302 cfg
->basename
, cfg
->basename
, cfg
->basename
, cfg
->basename
1306 if (cfg
->modtype
== MCC
|| cfg
->modtype
== MUI
|| cfg
->modtype
== MCP
)
1310 " &AROS_SLIB_ENTRY(MCC_Query,%s,%d),\n",
1314 else if (cfg
->modtype
== DATATYPE
)
1318 " &AROS_SLIB_ENTRY(ObtainEngine,%s,%d),\n",
1323 else /* NORESIDENT */
1325 if (cfg
->modtype
!= RESOURCE
&& cfg
->modtype
!= HANDLER
)
1328 struct functionhead
*funclistit2
;
1330 if (funclistit
->lvo
!= 1)
1332 fprintf(stderr
, "Module without a generated resident structure has to provide the Open function (LVO==1)\n");
1336 funclistit
= funclistit
->next
;
1338 if (funclistit
->lvo
!= 2)
1340 fprintf(stderr
, "Module without a generated resident structure has to provide the Close function (LVO==2)\n");
1344 funclistit
= funclistit
->next
;
1346 if (funclistit
->lvo
== 3)
1347 funclistit
= funclistit
->next
;
1351 if (funclistit
->lvo
== 4)
1352 funclistit
= funclistit
->next
;
1359 "AROS_UFH1S(int, %s_null,\n"
1360 " AROS_UFHA(struct Library *, libbase, A6)\n"
1363 " AROS_USERFUNC_INIT\n"
1365 " AROS_USERFUNC_EXIT\n"
1370 funclistit
= cfg
->funclist
;
1371 funclistit2
= funclistit
->next
;
1374 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1376 " &AROS_SLIB_ENTRY(%s,%s,%d),\n"
1377 " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1378 funclistit
->internalname
, cfg
->basename
, lvo
+1,
1379 funclistit2
->internalname
, cfg
->basename
, lvo
+2
1382 funclistit
= funclistit2
->next
;
1384 if (funclistit
->lvo
== 3)
1386 fprintf(out
, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1387 funclistit
->internalname
, cfg
->basename
, lvo
+1
1389 funclistit
= funclistit
->next
;
1392 fprintf(out
, " &%s_null,\n", cfg
->modulename
);
1395 if (funclistit
->lvo
== 4)
1397 fprintf(out
, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1398 funclistit
->internalname
, cfg
->basename
, lvo
+1
1400 funclistit
= funclistit
->next
;
1403 fprintf(out
, " &%s_null,\n", cfg
->modulename
);
1410 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1415 while (funclistit
!= NULL
)
1417 for (i
= lvo
+1; i
<funclistit
->lvo
; i
++)
1418 fprintf(out
, " NULL,\n");
1419 lvo
= funclistit
->lvo
;
1421 switch (funclistit
->libcall
)
1424 fprintf(out
, " &%s,\n", funclistit
->internalname
1430 if (funclistit
->version
!= lastversion
) {
1431 lastversion
= funclistit
->version
;
1432 fprintf(out
, " /* Version %d */\n", lastversion
);
1434 fprintf(out
, " &AROS_SLIB_ENTRY(%s,%s,%d),\n", funclistit
->internalname
, cfg
->basename
, lvo
);
1438 fprintf(stderr
, "Internal error: unhandled libcall type in writestart\n");
1443 funclistit
= funclistit
->next
;
1446 fprintf(out
, " (void *)-1\n};\n");
1450 static void writesets(FILE *out
, struct config
*cfg
)
1455 "DEFINESET(CTORS)\n"
1456 "DEFINESET(DTORS)\n"
1458 if (cfg
->modtype
!= HANDLER
)
1460 "DEFINESET(INITLIB)\n"
1461 "DEFINESET(EXPUNGELIB)\n"
1463 if (!(cfg
->options
& OPTION_NOOPENCLOSE
))
1465 "DEFINESET(OPENLIB)\n"
1466 "DEFINESET(CLOSELIB)\n"
1468 if (cfg
->modtype
== DEVICE
)
1470 "DEFINESET(OPENDEV)\n"
1471 "DEFINESET(CLOSEDEV)\n"
1473 if (cfg
->classlist
!= NULL
)
1475 "DEFINESET(CLASSESINIT)\n"
1476 "DEFINESET(CLASSESEXPUNGE)\n"