- Undefine also UtilityBase, fixes conflict with #include <proto/utility.h> below
[AROS.git] / tools / genmodule / writestart.c
blob75d359b501eeaff3e3559e35249194b9d4e4ee01
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Print the library magic and init code in the file modname_start.c.
6 This code is partly based on code in CLib37x.lha from Andreas R. Kleinert
7 */
8 #include "genmodule.h"
9 #include "oopsupport.h"
10 #include "muisupport.h"
11 #include "dtsupport.h"
12 #include "boopsisupport.h"
14 static void writedecl(FILE *, struct config *);
15 static void writedeclsets(FILE *, struct config *);
16 static void writeresident(FILE *, struct config *);
17 static void writeinitlib(FILE *, struct config *);
18 static void writehandler(FILE *, struct config *);
19 static void writeopenlib(FILE *, struct config *);
20 static void writecloselib(FILE *, struct config *);
21 static void writeexpungelib(FILE *, struct config *);
22 static void writeextfunclib(FILE *, struct config *);
23 static void writefunctable(FILE *, struct config *);
24 static void writesets(FILE *, struct config *);
26 static inline const char *upname(const char *s)
28 static char name[512];
29 int i = 0;
31 while (s && i < (sizeof(name)-1))
32 name[i++] = toupper(*(s++));
33 name[i] = 0;
35 return &name[0];
39 /* Some general info on the function of the generated code and how they work
40 for .library modules (TODO: add docs for other module types):
42 The code in this file will write out the inittable, the function table,
43 the InitLib, OpenLib, CloseLib and ExpungeLib function.
44 InitLib will call the functions in the ADD2INIT symbolset.
45 OpenLib will call the functions in the ADD2OPENLIB symbolset.
46 CloseLib will call the functions in the ADD2CLOSELIB symbolset.
47 ExpungeLib will call the fucntions in the ADD2EXIT symbolset.
49 Currently 3 types of libraries are supported: 1 libbase, a per-opener
50 libbase and a per-task libbase.
51 * For 1 libbase the libbase is initialized once in InitLib and
52 then returned for each call to OpenLib. OpenLib and CloseLib keep track
53 of the times the libraries is still open; if it is 0 the library may be
54 expunged.
55 * The per-opener libbase will create a new libbase for each call to OpenLib
56 After InitLib has called the ADD2INIT functions the fields in the root
57 libbase may have been initialized to a certain value. These value are
58 copied in the newly generated libbase and then the ADD2OPENLIB functions
59 are called with the new libbase.
60 A per-opener libbase is indicated by the OPTION_DUPBASE flag in cfg->options.
61 Currently, a task memory slot is used to store the libbase when a function
62 of the library is entered. With proper support from the compiler this could
63 be changed to use a reserved register - probably increasing speed. This
64 could be implemented later on without breaking backwards compatibility.
65 Special provision has been taken to restore the state of the memory slot
66 after CloseLib to what it was when OpenLib is called. This is to handle the
67 case properly where the library is used both in the parent and child
68 of a Task run with RunCommand().
69 * The per-task libbase will create a new libbase for a call to OpenLib when
70 there does not exist a libbase yet for this task. This is handled by reserving
71 an additional task memory slot. In OpenLib the contents of this memory slot
72 is checked and only a new libbase will be generated when the libbase stored
73 there is not for the current Task. Also on then the ADD2OPENLIB
74 A separate counter is added to count the number of times the libbase is opened
75 in the same task. The libbase will also only be closed and removed if this
76 counter reaches 0 and only then the ADD2CLOSELIB functions are called.
77 A per-task libbase is indicated by both flags OPTION_DUPBASE and
78 OPTION_PERTASKBASE in cfg->options.
79 It was decided to use an extra slot for storing the per-task libbase to check
80 in OpenLib if a new libbase has to created. This is to increase flexibility
81 during calling of the library functions. If the library supports this the
82 library can still be called with another libbase then the libbase stored in the
83 per-task slot, or the library function can be called from another task then the
84 one that opened the libbase.
85 Also here special provision has been taken to restore the state of the memory
86 slot after CloseLib to what it was when OpenLib is called.
88 void writestart(struct config *cfg)
90 FILE *out;
91 char line[256], *banner;
92 struct classinfo *cl;
94 snprintf(line, 255, "%s/%s_start.c", cfg->gendir, cfg->modulename);
95 out = fopen(line, "w");
97 if (out == NULL)
99 perror(line);
100 exit(20);
103 banner = getBanner(cfg);
104 fprintf(out, "%s", banner);
105 freeBanner(banner);
107 fprintf(out,
108 "/* For comments and explanation of generated code look in writestart.c source code\n"
109 " of the genmodule program */\n"
112 writedecl(out, cfg);
113 if (!(cfg->options & OPTION_NORESIDENT))
115 writeresident(out, cfg);
116 writedeclsets(out, cfg);
117 writeinitlib(out, cfg);
118 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
120 writeopenlib(out, cfg);
121 writecloselib(out, cfg);
122 writeexpungelib(out, cfg);
123 writeextfunclib(out, cfg);
124 if (cfg->modtype == MCC || cfg->modtype == MUI || cfg->modtype == MCP)
125 writemccquery(out, cfg);
126 else if (cfg->modtype == DATATYPE)
127 writeobtainengine(out, cfg);
129 writesets(out, cfg);
132 if (cfg->modtype != HANDLER)
133 writefunctable(out, cfg);
135 for (cl = cfg->classlist; cl != NULL; cl = cl->next)
137 switch (cl->classtype)
139 case MCC:
140 case MUI:
141 case MCP:
142 /* Second argument to next call: the class is not the main class if it is not
143 * the first class or the modtype is not a MUI class
145 writemccinit(cfg, out, cl != cfg->classlist || cfg->modtype != cl->classtype, cl);
146 break;
147 case GADGET:
148 case DATATYPE:
149 case CLASS:
150 case IMAGE:
151 writeclassinit(cfg, out, cl);
152 break;
153 case HIDD:
154 writeoopinit(out, cl);
155 break;
156 default:
157 fprintf(stdout, "Internal error: unsupported classtype in writestart\n");
158 exit(20);
162 fclose(out);
166 static void writedecl(FILE *out, struct config *cfg)
168 struct stringlist *linelistit, *s;
169 int boopsiinc=0, muiinc=0, oopinc=0;
170 struct functionhead *funclistit;
171 struct functionarg *arglistit;
172 struct classinfo *classlistit;
173 char *type, *name;
175 if (cfg->modtype == DEVICE)
177 fprintf(out,
178 "#include <exec/io.h>\n"
179 "#include <exec/errors.h>\n"
182 fprintf(out,
183 "#include <exec/types.h>\n"
184 "#include <exec/libraries.h>\n"
185 "#include <exec/resident.h>\n"
186 "#include <aros/libcall.h>\n"
187 "#include <aros/asmcall.h>\n"
188 "#include <aros/symbolsets.h>\n"
189 "#include <aros/genmodule.h>\n"
190 "#include <dos/dos.h>\n"
191 "\n"
192 "#include \"%s_libdefs.h\"\n"
193 "\n"
194 , cfg->modulename
196 for (s = cfg->rellibs; s; s = s->next)
197 fprintf(out,
198 "#include <proto/%s.h>\n"
199 , s->s
201 fprintf(out,
202 "\n"
203 "#undef SysBase\n"
204 "#undef OOPBase\n"
205 "#undef UtilityBase\n"
206 "\n"
207 "#include <proto/exec.h>\n"
208 "#include <proto/alib.h>\n"
209 "\n"
212 /* Write out declaration section provided in the config file */
213 for (linelistit = cfg->cdeflines; linelistit != NULL; linelistit = linelistit->next)
215 fprintf(out, "%s\n", linelistit->s);
218 /* Is there a variable for storing the segList ? */
219 if (!(cfg->options & OPTION_NOEXPUNGE) && cfg->modtype!=RESOURCE && cfg->modtype != HANDLER)
221 fprintf(out,
222 "#ifndef GM_SEGLIST_FIELD\n"
223 "static BPTR __attribute__((unused)) GM_UNIQUENAME(seglist);\n"
224 "#define GM_SEGLIST_FIELD(LIBBASE) (GM_UNIQUENAME(seglist))\n"
225 "#endif\n"
228 if (cfg->options & OPTION_DUPBASE)
229 fprintf(out,
230 "/* Required for TaskStorage manipulation */\n"
231 "extern struct ExecBase *SysBase;\n"
233 if (cfg->options & OPTION_DUPBASE)
235 fprintf(out,
236 "#ifndef GM_ROOTBASE_FIELD\n"
237 "static LIBBASETYPEPTR GM_UNIQUENAME(rootbase);\n"
238 "#define GM_ROOTBASE_FIELD(LIBBASE) (GM_UNIQUENAME(rootbase))\n"
239 "#endif\n"
240 "struct __GM_DupBase {\n"
241 " LIBBASETYPE base;\n"
242 " LIBBASETYPEPTR oldbase;\n"
244 if (cfg->options & OPTION_PERTASKBASE)
246 fprintf(out,
247 " ULONG taskopencount;\n"
248 " struct Task *task;\n"
249 " APTR retaddr;\n"
250 " LIBBASETYPEPTR oldpertaskbase;\n"
253 fprintf(out,
254 "};\n"
256 if (cfg->options & OPTION_PERTASKBASE)
258 fprintf(out,
259 "static LONG __pertaskslot;\n"
260 "LIBBASETYPEPTR __GM_GetBaseParent(LIBBASETYPEPTR base)\n"
261 "{\n"
262 " return ((struct __GM_DupBase *)base)->oldpertaskbase;\n"
263 "}\n"
264 "static inline LIBBASETYPEPTR __GM_GetPerTaskBase(void)\n"
265 "{\n"
266 " return (LIBBASETYPEPTR)GetTaskStorageSlot(__pertaskslot);\n"
267 "}\n"
268 "static inline void __GM_SetPerTaskBase(LIBBASETYPEPTR base)\n"
269 "{\n"
270 " SetTaskStorageSlot(__pertaskslot, (IPTR)base);\n"
271 "}\n"
276 /* Set the size of the library base to accomodate the relbases */
277 if (cfg->options & OPTION_DUPBASE)
279 fprintf(out,
280 "#define LIBBASESIZE (sizeof(struct __GM_DupBase) + sizeof(struct Library *)*%d)\n"
281 , slist_length(cfg->rellibs)
284 } else {
285 fprintf(out,
286 "#define LIBBASESIZE (sizeof(LIBBASETYPE) + sizeof(struct Library *)*%d)\n"
287 , slist_length(cfg->rellibs)
291 if (cfg->rellibs) {
292 struct stringlist *sl;
293 int i, n = slist_length(cfg->rellibs);
295 for (sl=cfg->rellibs; sl; sl=sl->next, n--) {
296 fprintf(out,
297 "#ifndef AROS_RELLIB_OFFSET_%s\n"
298 "# error '%s' is not a relative library\n"
299 "#endif\n"
300 "const IPTR AROS_RELLIB_OFFSET_%s = LIBBASESIZE-sizeof(struct Library *)*%d;\n"
301 , upname(sl->s)
302 , sl->s
303 , upname(sl->s)
309 if (cfg->options & OPTION_DUPBASE) {
310 fprintf(
311 out,
312 "static LONG __GM_BaseSlot;\n"
313 "char *__aros_getoffsettable(void)\n"
314 "{\n"
315 " return (char *)GetTaskStorageSlot(__GM_BaseSlot);\n"
316 "}\n"
317 "void __aros_setoffsettable(void *base)\n"
318 "{\n"
319 " SetTaskStorageSlot(__GM_BaseSlot, (IPTR)base);\n"
320 "}\n"
321 "%s__aros_getbase_%s(void)\n"
322 "{\n"
323 " return (%s)__aros_getoffsettable();\n"
324 "}\n",
325 cfg->libbasetypeptrextern, cfg->libbase,
326 cfg->libbasetypeptrextern
328 } else if (cfg->rellibs || (cfg->options & OPTION_STACKCALL)) {
329 fprintf(out,
330 "#ifdef __aros_getoffsettable\n"
332 if ((cfg->options & OPTION_STACKCALL))
333 fprintf(out,
334 "#error Redefining __aros_setoffsettable is not permitted with stackcall APIs\n"
336 else
337 fprintf(out,
338 "#define __aros_getbase_%s() __aros_getoffsettable()\n",
339 cfg->libbase
341 fprintf(out,
342 "#else /* !__aros_getoffsettable */\n"
343 "static char *__GM_OffsetTable;\n"
344 "char *__aros_getoffsettable(void)\n"
345 "{\n"
346 " return __GM_OffsetTable;\n"
347 "}\n"
348 "BOOL __aros_setoffsettable(char *base)\n"
349 "{\n"
350 " __GM_OffsetTable = base;\n"
351 " return TRUE;\n"
352 "}\n"
353 "%s__aros_getbase_%s(void)\n"
354 "{\n"
355 " return (%s)__aros_getoffsettable();\n"
356 "}\n"
357 "#endif /* __aros_getoffsettable */\n"
358 "\n",
359 cfg->libbasetypeptrextern, cfg->libbase,
360 cfg->libbasetypeptrextern
364 if (cfg->rellibs)
366 struct stringlist *sl;
368 for (sl = cfg->rellibs; sl; sl = sl->next)
370 fprintf(out,
371 "AROS_IMPORT_ASM_SYM(void *,__GM_rellib_base_%s,AROS_RELLIB_BASE_%s);\n"
372 , sl->s
373 , upname(sl->s)
378 for (classlistit = cfg->classlist; classlistit != NULL; classlistit = classlistit->next)
380 /* For the main class basename is the same as the module basename */
381 if (strcmp(classlistit->basename, cfg->basename) == 0)
383 if (classlistit->classptr_var == NULL)
385 fprintf(out,
386 "#if !defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
387 "static APTR GM_UNIQUENAME(%sClass);\n"
388 "#define GM_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
389 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
390 "#define %s_STORE_CLASSPTR 1\n"
391 "#elif defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
392 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_CLASSPTR_FIELD(LIBBASE))\n"
393 "#elif !defined(GM_CLASSPTR_FIELD) && defined(%s_CLASSPTR_FIELD)\n"
394 "#define GM_CLASSPTR_FIELD(LIBBASE) (%s_CLASSPTR_FIELD(LIBBASE))\n"
395 "#endif\n",
396 classlistit->basename,
397 classlistit->basename,
398 classlistit->basename,
399 classlistit->basename, classlistit->basename,
400 classlistit->basename,
401 classlistit->basename,
402 classlistit->basename,
403 classlistit->basename,
404 classlistit->basename
407 else
409 fprintf(out,
410 "#define GM_CLASSPTR_FIELD(LIBBASE) (%s)\n"
411 "#define %s_CLASSPTR_FIELD(LIBBASE) (%s)\n"
412 "#define %s_STORE_CLASSPTR 1\n",
413 classlistit->classptr_var,
414 classlistit->basename, classlistit->classptr_var,
415 classlistit->basename
419 else
421 if (classlistit->classptr_var == NULL)
423 fprintf(out,
424 "#if !defined(%s_CLASSPTR_FIELD)\n"
425 "static APTR GM_UNIQUENAME(%sClass);\n"
426 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
427 "#define %s_STORE_CLASSPTR 1\n"
428 "#endif\n",
429 classlistit->basename,
430 classlistit->basename,
431 classlistit->basename, classlistit->basename,
432 classlistit->basename
435 else
437 fprintf(out,
438 "#define %s_CLASSPTR_FIELD(LIBBASE) (%s)\n"
439 "#define %s_STORE_CLASSPTR 1\n",
440 classlistit->basename, classlistit->classptr_var,
441 classlistit->basename
447 /* Write out the defines for the functions of the function table */
448 writefuncdefs(out, cfg, cfg->funclist);
449 /* Write internal stubs */
450 writefuncinternalstubs(out, cfg, cfg->funclist);
451 fprintf(out, "\n");
454 /* Write out the includes needed for the classes */
455 if (cfg->classlist != NULL)
456 writeboopsiincludes(out);
458 for (classlistit = cfg->classlist; classlistit != NULL; classlistit = classlistit->next)
460 switch (classlistit->classtype)
462 case MUI:
463 case MCC:
464 case MCP:
465 if (!muiinc)
467 writemuiincludes(out);
468 muiinc = 1;
470 /* Fall through: also write boopsi includes */
471 case GADGET:
472 case DATATYPE:
473 case CLASS:
474 case IMAGE:
475 if (!boopsiinc)
477 writeboopsiincludes(out);
478 boopsiinc = 1;
480 break;
481 case HIDD:
482 if (!oopinc)
484 writeoopincludes(out);
485 oopinc = 1;
487 break;
488 default:
489 fprintf(stderr, "Internal error: unhandled classtype in writedecl\n");
490 exit(20);
496 static void writedeclsets(FILE *out, struct config *cfg)
498 /* PROGRAM_ENTRIES is marked as handled but are just ignored in modules */
499 fprintf(out,
500 "THIS_PROGRAM_HANDLES_SYMBOLSET(INIT)\n"
501 "THIS_PROGRAM_HANDLES_SYMBOLSET(EXIT)\n"
502 "DECLARESET(INIT)\n"
503 "DECLARESET(EXIT)\n"
504 "THIS_PROGRAM_HANDLES_SYMBOLSET(PROGRAM_ENTRIES)\n"
505 "DECLARESET(PROGRAM_ENTRIES)\n"
507 if (cfg->modtype != HANDLER)
508 fprintf(out,
509 "THIS_PROGRAM_HANDLES_SYMBOLSET(CTORS)\n"
510 "THIS_PROGRAM_HANDLES_SYMBOLSET(DTORS)\n"
511 "DECLARESET(CTORS)\n"
512 "DECLARESET(DTORS)\n"
513 "THIS_PROGRAM_HANDLES_SYMBOLSET(INITLIB)\n"
514 "THIS_PROGRAM_HANDLES_SYMBOLSET(EXPUNGELIB)\n"
515 "DECLARESET(INITLIB)\n"
516 "DECLARESET(EXPUNGELIB)\n"
518 if (!(cfg->options & OPTION_NOAUTOLIB))
520 fprintf(out,
521 "THIS_PROGRAM_HANDLES_SYMBOLSET(LIBS)\n"
522 "DECLARESET(LIBS)\n"
524 if (cfg->rellibs)
525 fprintf(out,
526 "THIS_PROGRAM_HANDLES_SYMBOLSET(RELLIBS)\n"
527 "DECLARESET(RELLIBS)\n"
530 if (!(cfg->options & OPTION_NOOPENCLOSE))
531 fprintf(out,
532 "THIS_PROGRAM_HANDLES_SYMBOLSET(OPENLIB)\n"
533 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLOSELIB)\n"
534 "DECLARESET(OPENLIB)\n"
535 "DECLARESET(CLOSELIB)\n"
537 if (cfg->modtype == DEVICE)
538 fprintf(out,
539 "THIS_PROGRAM_HANDLES_SYMBOLSET(OPENDEV)\n"
540 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLOSEDEV)\n"
541 "DECLARESET(OPENDEV)\n"
542 "DECLARESET(CLOSEDEV)\n"
544 if (cfg->classlist != NULL)
545 fprintf(out,
546 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLASSESINIT)\n"
547 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLASSESEXPUNGE)\n"
548 "DECLARESET(CLASSESINIT)\n"
549 "DECLARESET(CLASSESEXPUNGE)\n"
550 "#define ADD2INITCLASSES(symbol, pri) ADD2SET(symbol, CLASSESINIT, pri)\n"
551 "#define ADD2EXPUNGECLASSES(symbol, pri) ADD2SET(symbol, CLASSESEXPUNGE, pri)\n"
553 fprintf(out, "\n");
557 static void writeresident(FILE *out, struct config *cfg)
559 char *rt_skip = cfg->addromtag;
561 if (rt_skip)
562 fprintf(out, "extern const struct Resident %s;\n", rt_skip);
563 else
565 rt_skip = "GM_UNIQUENAME(End)";
566 fprintf(out, "extern const int %s;\n", rt_skip);
568 fprintf(out,
569 "extern const APTR GM_UNIQUENAME(FuncTable)[];\n"
571 if (cfg->options & OPTION_RESAUTOINIT)
572 fprintf(out, "static const struct InitTable GM_UNIQUENAME(InitTable);\n");
573 fprintf(out,
574 "\n"
575 "extern const char GM_UNIQUENAME(LibName)[];\n"
576 "extern const char GM_UNIQUENAME(LibID)[];\n"
577 "extern const char GM_UNIQUENAME(Copyright)[];\n"
578 "\n"
581 if (cfg->options & OPTION_RESAUTOINIT)
583 fprintf(out,
584 "#define __freebase(LIBBASE)\\\n"
585 "do {\\\n"
586 " UWORD negsize, possize;\\\n"
587 " UBYTE *negptr = (UBYTE *)LIBBASE;\\\n"
588 " negsize = ((struct Library *)LIBBASE)->lib_NegSize;\\\n"
589 " negptr -= negsize;\\\n"
590 " possize = ((struct Library *)LIBBASE)->lib_PosSize;\\\n"
591 " FreeMem (negptr, negsize+possize);\\\n"
592 "} while(0)\n"
593 "\n");
596 fprintf(out,
597 "AROS_UFP3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
598 " AROS_UFPA(LIBBASETYPEPTR, LIBBASE, D0),\n"
599 " AROS_UFPA(BPTR, segList, A0),\n"
600 " AROS_UFPA(struct ExecBase *, sysBase, A6)\n"
601 ");\n"
603 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
605 fprintf(out,
606 "AROS_LD1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
607 " AROS_LDA(LIBBASETYPEPTR, extralh, D0),\n"
608 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
609 ");\n"
610 "\n",
611 cfg->basename
614 fprintf(out,
615 "struct Resident const GM_UNIQUENAME(ROMTag) =\n"
616 "{\n"
617 " RTC_MATCHWORD,\n"
618 " (struct Resident *)&GM_UNIQUENAME(ROMTag),\n"
619 " (APTR)&%s,\n"
620 " RESIDENTFLAGS,\n"
621 " VERSION_NUMBER,\n",
622 rt_skip
624 switch (cfg->modtype)
626 case LIBRARY:
627 case MUI:
628 case MCC:
629 case MCP:
630 case GADGET:
631 case DATATYPE:
632 case USBCLASS:
633 case HIDD:
634 fprintf(out, " NT_LIBRARY,\n");
635 break;
636 case DEVICE:
637 fprintf(out, " NT_DEVICE,\n");
638 break;
639 case RESOURCE:
640 case HANDLER:
641 fprintf(out, " NT_RESOURCE,\n");
642 break;
643 default:
644 fprintf(stderr, "Internal error: unsupported modtype for NT_...\n");
645 exit(20);
646 break;
648 fprintf(out,
649 " RESIDENTPRI,\n"
650 " (CONST_STRPTR)&GM_UNIQUENAME(LibName)[0],\n"
651 " (CONST_STRPTR)&GM_UNIQUENAME(LibID)[6],\n"
653 if (cfg->options & OPTION_RESAUTOINIT)
655 fprintf(out,
656 " (APTR)&GM_UNIQUENAME(InitTable)\n"
657 "};\n"
658 "\n"
659 "static struct InitTable\n"
660 "{\n"
661 " IPTR Size;\n"
662 " const APTR *FuncTable;\n"
663 " struct DataTable *DataTable;\n"
664 " APTR InitLibTable;\n"
665 "}\n"
666 "const GM_UNIQUENAME(InitTable) =\n"
667 "{\n"
668 " LIBBASESIZE,\n"
669 " &GM_UNIQUENAME(FuncTable)[0],\n"
670 " NULL,\n"
671 " (APTR)GM_UNIQUENAME(InitLib)\n"
672 "};\n"
675 else
676 fprintf(out, " (APTR)GM_UNIQUENAME(InitLib)\n};\n");
678 fprintf(out,
679 "\n"
680 "const char GM_UNIQUENAME(LibName)[] = MOD_NAME_STRING;\n"
681 "const char GM_UNIQUENAME(LibID)[] = VERSION_STRING;\n"
682 "const char GM_UNIQUENAME(Copyright)[] = COPYRIGHT_STRING;\n"
683 "\n"
687 static void writehandler(FILE *out, struct config *cfg)
689 int i, handlers=0;
690 struct handlerinfo *hl;
691 int need_fse = 0, need_dos = 0;
693 fprintf(out,
694 "\n"
695 "#include <resources/filesysres.h>\n"
696 "#include <aros/system.h>\n"
697 "#include <proto/arossupport.h>\n"
698 "#include <proto/expansion.h>\n"
699 "\n"
702 for (hl = cfg->handlerlist; hl != NULL; hl = hl->next) {
703 if (hl->type == HANDLER_DOSNODE)
704 need_dos = 1;
705 else
706 need_fse = 1;
707 handlers++;
710 fprintf(out,
711 "\n"
712 "LONG %s(struct ExecBase *sysBase);\n"
713 "extern const LONG const __aros_libreq_SysBase __attribute__((weak));\n"
714 "\n"
715 "__startup AROS_PROCH(GM_UNIQUENAME(Handler), argptr, argsize, SysBase)\n"
716 "{\n"
717 " AROS_PROCFUNC_INIT\n"
718 "\n"
719 " LONG ret = RETURN_FAIL;\n"
720 "\n"
721 " if (!SysBase || SysBase->LibNode.lib_Version < __aros_libreq_SysBase)\n"
722 " return ERROR_INVALID_RESIDENT_LIBRARY;\n"
723 " if (set_call_funcs(SETNAME(INIT), 1, 1)) {\n"
724 " ret = %s(SysBase);\n"
725 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
726 " }\n"
727 "\n"
728 " return ret;\n"
729 "\n"
730 " AROS_PROCFUNC_EXIT\n"
731 "}\n"
732 , cfg->handlerfunc
733 , cfg->handlerfunc
736 fprintf(out,
737 "\n"
738 "static inline BOOL GM_UNIQUENAME(InitHandler)(struct ExecBase *SysBase)\n"
739 "{\n"
742 if (!need_dos && !need_fse) {
743 fprintf(out,
744 " return TRUE;\n"
745 "}\n"
747 return;
750 fprintf(out,
751 " BPTR seg;\n"
754 if (need_dos) {
755 fprintf(out,
756 " struct Library *ExpansionBase;\n"
759 if (need_fse) {
760 fprintf(out,
761 " struct FileSysResource *fsr;\n"
762 " struct FileSysEntry *fse;\n"
765 if (need_fse) {
766 fprintf(out,
767 " fsr = (struct FileSysResource *)OpenResource(\"FileSystem.resource\");\n"
768 " if (fsr == NULL)\n"
769 " return FALSE;\n"
772 if (need_dos) {
773 fprintf(out,
774 " ExpansionBase = OpenLibrary(\"expansion.library\", 36);\n"
775 " if (ExpansionBase == NULL)\n"
776 " return FALSE;\n"
779 fprintf(out,
780 " seg = CreateSegList(GM_UNIQUENAME(Handler));\n"
781 " if (seg != BNULL) {\n"
783 for (hl = cfg->handlerlist; hl != NULL; hl = hl->next)
785 switch (hl->type)
787 case HANDLER_DOSNODE:
788 fprintf(out,
789 "\n"
790 " {\n"
791 " struct DeviceNode *node;\n"
792 " IPTR pp[] = { \n"
793 " (IPTR)\"%s\",\n"
794 " (IPTR)NULL,\n"
795 " (IPTR)0,\n"
796 " (IPTR)0,\n"
797 " (IPTR)0\n"
798 " };\n"
799 " node = MakeDosNode((APTR)pp);\n"
800 " if (node) {\n"
801 " node->dn_StackSize = %u;\n"
802 " node->dn_SegList = seg;\n"
803 " node->dn_Startup = (BPTR)%d;\n"
804 " node->dn_Priority = %d;\n"
805 " node->dn_GlobalVec = (BPTR)(SIPTR)-1;\n"
806 " AddBootNode(%d, 0, node, NULL);\n"
807 " }\n"
808 " }\n"
809 "\n"
810 , hl->name
811 , hl->stacksize
812 , hl->startup
813 , hl->priority
814 , hl->bootpri
816 break;
817 case HANDLER_RESIDENT:
818 case HANDLER_DOSTYPE:
819 fprintf(out,
820 "\n"
821 " /* Check to see if we can allocate the memory for the fse */\n"
822 " fse = AllocMem(sizeof(*fse), MEMF_CLEAR);\n"
823 " if (fse) {\n"
824 " fse->fse_Node.ln_Name = VERSION_STRING;\n"
825 " fse->fse_Node.ln_Pri = %d;\n"
826 " fse->fse_DosType = 0x%08x;\n"
827 " fse->fse_Version = (MAJOR_VERSION << 16) | MINOR_VERSION;\n"
828 " fse->fse_PatchFlags = FSEF_SEGLIST | FSEF_GLOBALVEC | FSEF_PRIORITY;\n"
829 , hl->autodetect
830 , hl->id
832 if (hl->stacksize)
834 fprintf(out,
835 " fse->fse_PatchFlags |= FSEF_STACKSIZE;\n"
836 " fse->fse_StackSize = %d;\n"
837 , hl->stacksize
840 if (hl->name)
841 fprintf(out,
842 " fse->fse_PatchFlags |= FSEF_HANDLER;\n"
843 " fse->fse_Handler = AROS_CONST_BSTR(\"%s\");\n"
844 , hl->name);
845 fprintf(out,
846 " fse->fse_Priority = %d;\n"
847 " fse->fse_SegList = seg;\n"
848 " fse->fse_GlobalVec = (BPTR)(SIPTR)-1;\n"
849 " fse->fse_Startup = (BPTR)%d;\n"
850 "\n"
851 " /* Add to the list. I know forbid and permit are\n"
852 " * a little unnecessary for the pre-multitasking state\n"
853 " * we should be in at this point, but you never know\n"
854 " * who's going to blindly copy this code as an example.\n"
855 " */\n"
856 " Forbid();\n"
857 " Enqueue(&fsr->fsr_FileSysEntries, (struct Node *)fse);\n"
858 " Permit();\n"
859 " }\n"
860 , hl->priority
861 , hl->startup
863 break;
866 fprintf(out,
867 " }\n"
869 if (need_dos) {
870 fprintf(out,
871 " CloseLibrary(ExpansionBase);\n"
874 fprintf(out,
875 " return TRUE;\n"
876 "}\n"
877 "\n"
881 static void writeinitlib(FILE *out, struct config *cfg)
883 if (cfg->handlerlist)
884 writehandler(out, cfg);
886 fprintf(out,
887 "extern const LONG const __aros_libreq_SysBase __attribute__((weak));\n"
888 "\n"
889 "AROS_UFH3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
890 " AROS_UFHA(LIBBASETYPEPTR, LIBBASE, D0),\n"
891 " AROS_UFHA(BPTR, segList, A0),\n"
892 " AROS_UFHA(struct ExecBase *, sysBase, A6)\n"
893 ")\n"
894 "{\n"
895 " AROS_USERFUNC_INIT\n"
898 if (cfg->modtype == HANDLER) {
899 fprintf(out,
900 "\n"
901 " GM_UNIQUENAME(InitHandler)(sysBase);\n"
902 " return LIBBASE;\n"
903 "\n"
904 " AROS_USERFUNC_EXIT\n"
905 "}\n"
906 "\n"
908 return;
911 fprintf(out,
912 "\n"
913 " int ok;\n"
914 " int initcalled = 0;\n"
916 /* Set the global SysBase, needed for __aros_setoffsettable()/__aros_getoffsettable() */
917 if (cfg->options & OPTION_DUPBASE)
918 fprintf(out,
919 " SysBase = sysBase;\n"
921 else
922 fprintf(out,
923 " struct ExecBase *SysBase = sysBase;\n"
925 fprintf(out,
926 "\n"
927 "#ifdef GM_SYSBASE_FIELD\n"
928 " GM_SYSBASE_FIELD(LIBBASE) = (APTR)SysBase;\n"
929 "#endif\n"
930 " if (!SysBase || SysBase->LibNode.lib_Version < __aros_libreq_SysBase)\n"
931 " return NULL;\n"
932 "\n"
935 if (cfg->options & OPTION_RESAUTOINIT) {
936 fprintf(out,
937 "#ifdef GM_OOPBASE_FIELD\n"
938 " GM_OOPBASE_FIELD(LIBBASE) = OpenLibrary(\"oop.library\",0);\n"
939 " if (GM_OOPBASE_FIELD(LIBBASE) == NULL)\n"
940 " return NULL;\n"
941 "#endif\n"
945 if (!(cfg->options & OPTION_RESAUTOINIT))
947 fprintf(out,
948 " int vecsize;\n"
949 " struct Node *n;\n"
950 " char *mem;\n"
951 "\n"
952 " vecsize = FUNCTIONS_COUNT * LIB_VECTSIZE;\n"
953 " if (vecsize > 0)\n"
954 " vecsize = ((vecsize-1)/sizeof(IPTR) + 1)*sizeof(IPTR);\n"
955 " mem = AllocMem(vecsize+sizeof(LIBBASETYPE), MEMF_PUBLIC|MEMF_CLEAR);\n"
956 " if (mem == NULL)\n"
957 " return NULL;\n"
958 " LIBBASE = (LIBBASETYPEPTR)(mem + vecsize);\n"
959 " n = (struct Node *)LIBBASE;\n"
960 " n->ln_Type = NT_RESOURCE;\n"
961 " n->ln_Pri = RESIDENTPRI;\n"
962 " n->ln_Name = (char *)GM_UNIQUENAME(LibName);\n"
963 " MakeFunctions(LIBBASE, (APTR)GM_UNIQUENAME(FuncTable), NULL);\n"
965 if ((cfg->modtype != RESOURCE) && (cfg->options & OPTION_SELFINIT))
967 fprintf(out,
968 " ((struct Library*)LIBBASE)->lib_NegSize = vecsize;\n"
969 " ((struct Library*)LIBBASE)->lib_PosSize = sizeof(LIBBASETYPE);\n"
974 else
976 fprintf(out,
977 " ((struct Library *)LIBBASE)->lib_Revision = REVISION_NUMBER;\n"
981 if (cfg->options & OPTION_DUPBASE)
982 fprintf(out,
983 " __GM_BaseSlot = AllocTaskStorageSlot();\n"
984 " if (!SetTaskStorageSlot(__GM_BaseSlot, (IPTR)LIBBASE)) {\n"
985 " FreeTaskStorageSlot(__GM_BaseSlot);\n"
986 " return NULL;\n"
987 " }\n"
989 else if (cfg->rellibs || (cfg->options & OPTION_STACKCALL))
990 fprintf(out,
991 " __aros_setoffsettable((char *)LIBBASE);\n"
993 if (cfg->options & OPTION_PERTASKBASE)
994 fprintf(out,
995 " __pertaskslot = AllocTaskStorageSlot();\n"
998 if (!(cfg->options & OPTION_NOEXPUNGE) && cfg->modtype!=RESOURCE)
999 fprintf(out, " GM_SEGLIST_FIELD(LIBBASE) = segList;\n");
1000 if (cfg->options & OPTION_DUPBASE)
1001 fprintf(out, " GM_ROOTBASE_FIELD(LIBBASE) = (LIBBASETYPEPTR)LIBBASE;\n");
1002 fprintf(out, " if (");
1003 if (!(cfg->options & OPTION_NOAUTOLIB))
1004 fprintf(out, "set_open_libraries() && ");
1005 if (cfg->rellibs)
1006 fprintf(out, "set_open_rellibraries(LIBBASE) && ");
1007 fprintf(out,
1008 "set_call_funcs(SETNAME(INIT), 1, 1) &&"
1010 if (cfg->classlist != NULL)
1011 fprintf(out, "set_call_libfuncs(SETNAME(CLASSESINIT), 1, 1, LIBBASE) && ");
1012 fprintf(out,
1013 "1)\n"
1014 " {\n"
1015 " set_call_funcs(SETNAME(CTORS), -1, 0);\n"
1016 "\n"
1019 fprintf(out,
1020 " initcalled = 1;\n"
1021 " ok = set_call_libfuncs(SETNAME(INITLIB), 1, 1, LIBBASE);\n"
1022 " }\n"
1023 " else\n"
1024 " ok = 0;\n"
1025 "\n"
1026 " if (!ok)\n"
1027 " {\n"
1028 " if (initcalled)\n"
1029 " set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 0, LIBBASE);\n"
1030 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
1031 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
1033 if (cfg->classlist != NULL)
1034 fprintf(out, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, LIBBASE);\n");
1035 if (cfg->rellibs)
1036 fprintf(out, " set_close_rellibraries(LIBBASE);\n");
1037 if (!(cfg->options & OPTION_NOAUTOLIB))
1038 fprintf(out, " set_close_libraries();\n");
1040 if (cfg->options & OPTION_RESAUTOINIT)
1042 fprintf(out,
1043 "\n"
1044 " __freebase(LIBBASE);\n"
1047 else
1049 fprintf(out,
1050 "\n"
1051 " FreeMem(mem, vecsize+LIBBASESIZE);\n"
1054 fprintf(out,
1055 " return NULL;\n"
1056 " }\n"
1057 " else\n"
1058 " {\n"
1061 if (!(cfg->options & OPTION_RESAUTOINIT) && !(cfg->options & OPTION_SELFINIT))
1063 switch (cfg->modtype)
1065 case RESOURCE:
1066 fprintf(out, " AddResource(LIBBASE);\n");
1067 break;
1069 case DEVICE:
1070 fprintf(out, " AddDevice(LIBBASE);\n");
1072 default:
1073 /* Everything else is library */
1074 fprintf(out, " AddLibrary(LIBBASE);\n");
1075 break;
1079 fprintf(out,
1080 " return LIBBASE;\n"
1081 " }\n"
1082 "\n"
1083 " AROS_USERFUNC_EXIT\n"
1084 "}\n"
1085 "\n"
1089 static void writeopenlib(FILE *out, struct config *cfg)
1091 switch (cfg->modtype)
1093 case RESOURCE:
1094 fprintf(stderr, "Internal error: writeopenlib called for a resource\n");
1095 break;
1096 case HANDLER:
1097 fprintf(stderr, "Internal error: writeopenlib called for a handler\n");
1098 break;
1099 case DEVICE:
1100 if (cfg->options & OPTION_NOOPENCLOSE)
1101 fprintf(out,
1102 "AROS_LD3 (void, GM_UNIQUENAME(OpenLib),\n"
1103 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1104 " AROS_LDA(ULONG, unitnum, D0),\n"
1105 " AROS_LDA(ULONG, flags, D1),\n"
1106 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1107 ");\n",
1108 cfg->basename
1110 else
1112 fprintf(out,
1113 "AROS_LH3 (void, GM_UNIQUENAME(OpenLib),\n"
1114 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1115 " AROS_LHA(IPTR, unitnum, D0),\n"
1116 " AROS_LHA(ULONG, flags, D1),\n"
1117 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1118 ")\n",
1119 cfg->basename
1121 fprintf(out,
1122 "{\n"
1123 " AROS_LIBFUNC_INIT\n"
1124 "\n"
1125 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, LIBBASE)\n"
1126 " && set_call_devfuncs(SETNAME(OPENDEV), 1, 1, LIBBASE, ioreq, unitnum, flags)\n"
1127 " )\n"
1128 " {\n"
1129 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1130 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1131 "\n"
1132 " ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;\n"
1133 " }\n"
1134 " else\n"
1135 " {\n"
1136 " if (ioreq->io_Error >= 0)\n"
1137 " ioreq->io_Error = IOERR_OPENFAIL;\n"
1138 " }\n"
1139 "\n"
1140 " return;\n"
1141 "\n"
1142 " AROS_LIBFUNC_EXIT\n"
1143 "}\n"
1144 "\n"
1147 break;
1148 default:
1149 if (cfg->options & OPTION_NOOPENCLOSE)
1151 fprintf(out,
1152 "AROS_LD1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
1153 " AROS_LDA (ULONG, version, D0),\n"
1154 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1155 ");\n",
1156 cfg->basename
1158 return;
1160 fprintf(out,
1161 "AROS_LH1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
1162 " AROS_LHA (ULONG, version, D0),\n"
1163 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1164 ")\n"
1165 "{\n"
1166 " AROS_LIBFUNC_INIT\n"
1167 "\n",
1168 cfg->basename
1170 if (!(cfg->options & OPTION_DUPBASE))
1172 fprintf(out,
1173 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, LIBBASE) )\n"
1174 " {\n"
1175 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1176 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1177 " return LIBBASE;\n"
1178 " }\n"
1179 "\n"
1180 " return NULL;\n"
1181 "\n"
1182 " AROS_LIBFUNC_EXIT\n"
1183 "}\n"
1184 "\n"
1187 else /* OPTION_DUPBASE */
1189 fprintf(out,
1190 " struct Library *newlib = NULL;\n"
1191 " UWORD possize = ((struct Library *)LIBBASE)->lib_PosSize;\n"
1192 " LIBBASETYPEPTR oldbase = (LIBBASETYPEPTR)__aros_getbase_%s();\n",
1193 cfg->libbase
1195 if (cfg->options & OPTION_PERTASKBASE)
1196 fprintf(out,
1197 " struct Task *thistask = FindTask(NULL);\n"
1198 " LIBBASETYPEPTR oldpertaskbase = __GM_GetPerTaskBase();\n"
1199 " newlib = (struct Library *)oldpertaskbase;\n"
1200 " if (newlib)\n"
1201 " {\n"
1202 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1203 " if (dupbase->task != thistask)\n"
1204 " newlib = NULL;\n"
1205 " else if (thistask->tc_Node.ln_Type == NT_PROCESS\n"
1206 " && dupbase->retaddr != ((struct Process *)thistask)->pr_ReturnAddr\n"
1207 " )\n"
1208 " newlib = NULL;\n"
1209 " else\n"
1210 " dupbase->taskopencount++;\n"
1211 " }\n"
1214 fprintf(out,
1215 "\n"
1216 " if (newlib == NULL)\n"
1217 " {\n"
1218 " newlib = MakeLibrary(GM_UNIQUENAME(InitTable).FuncTable,\n"
1219 " GM_UNIQUENAME(InitTable).DataTable,\n"
1220 " NULL,\n"
1221 " GM_UNIQUENAME(InitTable).Size,\n"
1222 " (BPTR)NULL\n"
1223 " );\n"
1224 " if (newlib == NULL)\n"
1225 " return NULL;\n"
1226 "\n"
1227 " CopyMem(LIBBASE, newlib, possize);\n"
1228 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1229 " dupbase->oldbase = oldbase;\n"
1230 " __aros_setoffsettable((char *)newlib);\n"
1232 if (cfg->options & OPTION_PERTASKBASE)
1233 fprintf(out,
1234 " dupbase->task = thistask;\n"
1235 " if (thistask->tc_Node.ln_Type == NT_PROCESS)\n"
1236 " dupbase->retaddr = ((struct Process *)thistask)->pr_ReturnAddr;\n"
1237 " dupbase->oldpertaskbase = oldpertaskbase;\n"
1238 " dupbase->taskopencount = 1;\n"
1239 " __GM_SetPerTaskBase((LIBBASETYPEPTR)newlib);\n"
1241 fprintf(out,
1242 "\n"
1243 " if (!(set_open_rellibraries(newlib)\n"
1244 " && set_call_libfuncs(SETNAME(OPENLIB), 1, 1, newlib)\n"
1245 " )\n"
1246 " )\n"
1247 " {\n");
1248 if (cfg->options & OPTION_PERTASKBASE)
1249 fprintf(out,
1250 " __GM_SetPerTaskBase(oldpertaskbase);\n");
1251 fprintf(out,
1252 " __freebase(newlib);\n"
1253 " return NULL;\n"
1254 " }\n"
1255 "\n"
1256 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1257 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1258 " }\n"
1259 "\n"
1260 " return (LIBBASETYPEPTR)newlib;\n"
1261 "\n"
1262 " AROS_LIBFUNC_EXIT\n"
1263 "}\n"
1264 "\n"
1271 static void writecloselib(FILE *out, struct config *cfg)
1273 if (cfg->options & OPTION_NOOPENCLOSE)
1275 if (cfg->modtype != DEVICE)
1276 fprintf(out,
1277 "AROS_LD0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1278 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1279 ");\n",
1280 cfg->basename
1282 else
1283 fprintf(out,
1284 "AROS_LD1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1285 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1286 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1287 ");\n",
1288 cfg->basename
1290 return;
1292 if (cfg->modtype != DEVICE)
1293 fprintf(out,
1294 "AROS_LH0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1295 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1296 ")\n",
1297 cfg->basename
1299 else
1300 fprintf(out,
1301 "AROS_LH1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1302 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1303 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1304 ")\n",
1305 cfg->basename
1308 fprintf(out,
1309 "{\n"
1310 " AROS_LIBFUNC_INIT\n"
1311 "\n"
1313 if (cfg->modtype == DEVICE)
1314 fprintf(out,
1315 " if (!set_call_devfuncs(SETNAME(CLOSEDEV), -1, 1, LIBBASE, ioreq, 0, 0))\n"
1316 " {\n"
1317 " return BNULL;\n"
1318 " }\n"
1320 if (!(cfg->options & OPTION_DUPBASE))
1322 fprintf(out,
1323 " ((struct Library *)LIBBASE)->lib_OpenCnt--;\n"
1324 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, LIBBASE);\n"
1327 else /* OPTION_DUPBASE */
1329 fprintf(out,
1330 " LIBBASETYPEPTR rootbase = GM_ROOTBASE_FIELD(LIBBASE);\n"
1331 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)LIBBASE;\n"
1333 if (cfg->options & OPTION_PERTASKBASE)
1334 fprintf(out,
1335 " dupbase->taskopencount--;\n"
1336 " if (dupbase->taskopencount != 0)\n"
1337 " return BNULL;\n"
1339 fprintf(out,
1340 "\n"
1341 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, LIBBASE);\n"
1342 " set_close_rellibraries(LIBBASE);\n"
1343 " __aros_setoffsettable((char *)dupbase->oldbase);\n"
1345 if (cfg->options & OPTION_PERTASKBASE)
1346 fprintf(out,
1347 " __GM_SetPerTaskBase(((struct __GM_DupBase *)LIBBASE)->oldpertaskbase);\n"
1349 fprintf(out,
1350 " __freebase(LIBBASE);\n"
1351 " LIBBASE = rootbase;\n"
1352 " ((struct Library *)LIBBASE)->lib_OpenCnt--;\n"
1353 "\n"
1356 if (!(cfg->options & OPTION_NOEXPUNGE))
1357 fprintf(out,
1358 " if\n"
1359 " (\n"
1360 " (((struct Library *)LIBBASE)->lib_OpenCnt == 0)\n"
1361 " && (((struct Library *)LIBBASE)->lib_Flags & LIBF_DELEXP)\n"
1362 " )\n"
1363 " {\n"
1364 " return AROS_LC1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1365 " AROS_LCA(LIBBASETYPEPTR, LIBBASE, D0),\n"
1366 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
1367 " );\n"
1368 " }\n",
1369 cfg->basename
1371 fprintf(out,
1372 "\n"
1373 " return BNULL;\n"
1374 "\n"
1375 " AROS_LIBFUNC_EXIT\n"
1376 "}\n"
1377 "\n"
1382 static void writeexpungelib(FILE *out, struct config *cfg)
1384 fprintf(out,
1385 "AROS_LH1 (BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1386 " AROS_LHA(LIBBASETYPEPTR, extralh, D0),\n"
1387 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
1388 ")\n",
1389 cfg->basename
1391 fprintf(out,
1392 "{\n"
1393 " AROS_LIBFUNC_INIT\n"
1394 "\n"
1396 if (!(cfg->options & OPTION_NOEXPUNGE))
1398 if (cfg->options & OPTION_RESAUTOINIT) {
1399 fprintf(out,
1400 "#ifdef GM_SYSBASE_FIELD\n"
1401 " struct ExecBase *SysBase = (struct ExecBase *)GM_SYSBASE_FIELD(LIBBASE);\n"
1402 "#endif\n"
1405 fprintf(out,
1406 "\n"
1407 " if ( ((struct Library *)LIBBASE)->lib_OpenCnt == 0 )\n"
1408 " {\n"
1409 " BPTR seglist = GM_SEGLIST_FIELD(LIBBASE);\n"
1410 "\n"
1411 " if(!set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 1, LIBBASE))\n"
1412 " {\n"
1413 " ((struct Library *)LIBBASE)->lib_Flags |= LIBF_DELEXP;\n"
1414 " return BNULL;\n"
1415 " }\n"
1416 "\n"
1417 " Remove((struct Node *)LIBBASE);\n"
1418 "\n"
1419 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
1420 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
1422 if (cfg->classlist != NULL)
1423 fprintf(out, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, LIBBASE);\n");
1424 if (cfg->rellibs)
1425 fprintf(out, " set_close_rellibraries(LIBBASE);\n");
1426 if (!(cfg->options & OPTION_NOAUTOLIB))
1427 fprintf(out, " set_close_libraries();\n"
1428 "#ifdef GM_OOPBASE_FIELD\n"
1429 " CloseLibrary((struct Library *)GM_OOPBASE_FIELD(LIBBASE));\n"
1430 "#endif\n"
1432 if (cfg->options & OPTION_PERTASKBASE)
1433 fprintf(out,
1434 " FreeTaskStorageSlot(__pertaskslot);\n"
1435 " __pertaskslot = 0;\n"
1437 fprintf(out,
1438 "\n"
1439 " __freebase(LIBBASE);\n"
1440 "\n"
1441 " return seglist;\n"
1442 " }\n"
1443 "\n"
1444 " ((struct Library *)LIBBASE)->lib_Flags |= LIBF_DELEXP;\n"
1447 fprintf(out,
1448 "\n"
1449 " return BNULL;\n"
1450 "\n"
1451 " AROS_LIBFUNC_EXIT\n"
1452 "}\n"
1453 "\n"
1458 static void writeextfunclib(FILE *out, struct config *cfg)
1460 fprintf(out,
1461 "AROS_LH0 (LIBBASETYPEPTR, GM_UNIQUENAME(ExtFuncLib),\n"
1462 " LIBBASETYPEPTR, LIBBASE, 4, %s\n"
1463 ")\n"
1464 "{\n"
1465 " AROS_LIBFUNC_INIT\n"
1466 " return NULL;\n"
1467 " AROS_LIBFUNC_EXIT\n"
1468 "}\n"
1469 "\n",
1470 cfg->basename
1475 static void
1476 writefunctable(FILE *out,
1477 struct config *cfg
1480 struct functionhead *funclistit = cfg->funclist;
1481 struct functionarg *arglistit;
1482 unsigned int lvo;
1483 int i;
1484 char *name, *type;
1485 int lastversion = 0;
1487 /* lvo contains the number of functions already printed in the functable */
1488 lvo = 0;
1490 if (!(cfg->options & OPTION_NORESIDENT))
1492 fprintf(out,
1493 "\n"
1494 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1495 "{\n"
1497 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
1499 fprintf(out,
1500 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(OpenLib),%s,1),\n"
1501 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(CloseLib),%s,2),\n"
1502 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExpungeLib),%s,3),\n"
1503 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExtFuncLib),%s,4),\n",
1504 cfg->basename, cfg->basename, cfg->basename, cfg->basename
1506 lvo += 4;
1508 if (cfg->modtype == MCC || cfg->modtype == MUI || cfg->modtype == MCP)
1510 lvo++;
1511 fprintf(out,
1512 " &AROS_SLIB_ENTRY(MCC_Query,%s,%d),\n",
1513 cfg->basename, lvo
1516 else if (cfg->modtype == DATATYPE)
1518 lvo++;
1519 fprintf(out,
1520 " &AROS_SLIB_ENTRY(ObtainEngine,%s,%d),\n",
1521 cfg->basename, lvo
1525 else /* NORESIDENT */
1527 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
1529 int neednull = 0;
1530 struct functionhead *funclistit2;
1532 if (funclistit->lvo != 1)
1534 fprintf(stderr, "Module without a generated resident structure has to provide the Open function (LVO==1)\n");
1535 exit(20);
1537 else
1538 funclistit = funclistit->next;
1540 if (funclistit->lvo != 2)
1542 fprintf(stderr, "Module without a generated resident structure has to provide the Close function (LVO==2)\n");
1543 exit(20);
1545 else
1546 funclistit = funclistit->next;
1548 if (funclistit->lvo == 3)
1549 funclistit = funclistit->next;
1550 else
1551 neednull = 1;
1553 if (funclistit->lvo == 4)
1554 funclistit = funclistit->next;
1555 else
1556 neednull = 1;
1558 if (neednull)
1559 fprintf(out,
1560 "\n"
1561 "AROS_UFH1S(int, %s_null,\n"
1562 " AROS_UFHA(struct Library *, libbase, A6)\n"
1563 ")\n"
1564 "{\n"
1565 " AROS_USERFUNC_INIT\n"
1566 " return 0;\n"
1567 " AROS_USERFUNC_EXIT\n"
1568 "}\n",
1569 cfg->modulename
1572 funclistit = cfg->funclist;
1573 funclistit2 = funclistit->next;
1574 fprintf(out,
1575 "\n"
1576 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1577 "{\n"
1578 " &AROS_SLIB_ENTRY(%s,%s,%d),\n"
1579 " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1580 funclistit->internalname, cfg->basename, lvo+1,
1581 funclistit2->internalname, cfg->basename, lvo+2
1583 lvo += 2;
1584 funclistit = funclistit2->next;
1586 if (funclistit->lvo == 3)
1588 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1589 funclistit->internalname, cfg->basename, lvo+1
1591 funclistit = funclistit->next;
1593 else
1594 fprintf(out, " &%s_null,\n", cfg->modulename);
1595 lvo++;
1597 if (funclistit->lvo == 4)
1599 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1600 funclistit->internalname, cfg->basename, lvo+1
1602 funclistit = funclistit->next;
1604 else
1605 fprintf(out, " &%s_null,\n", cfg->modulename);
1606 lvo++;
1608 else
1610 fprintf(out,
1611 "\n"
1612 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1613 "{\n");
1617 while (funclistit != NULL)
1619 for (i = lvo+1; i<funclistit->lvo; i++)
1620 fprintf(out, " NULL,\n");
1621 lvo = funclistit->lvo;
1623 switch (funclistit->libcall)
1625 case STACK:
1626 case REGISTER:
1627 case REGISTERMACRO:
1628 if (funclistit->version != lastversion) {
1629 lastversion = funclistit->version;
1630 fprintf(out, " /* Version %d */\n", lastversion);
1632 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n", funclistit->internalname, cfg->basename, lvo);
1633 break;
1635 default:
1636 fprintf(stderr, "Internal error: unhandled libcall type in writestart\n");
1637 exit(20);
1638 break;
1641 funclistit = funclistit->next;
1644 fprintf(out, " (void *)-1\n};\n");
1648 static void writesets(FILE *out, struct config *cfg)
1650 fprintf(out,
1651 "DEFINESET(INIT)\n"
1652 "DEFINESET(EXIT)\n"
1654 if (cfg->modtype != HANDLER)
1655 fprintf(out,
1656 "DEFINESET(CTORS)\n"
1657 "DEFINESET(DTORS)\n"
1658 "DEFINESET(INITLIB)\n"
1659 "DEFINESET(EXPUNGELIB)\n"
1661 if (!(cfg->options & OPTION_NOOPENCLOSE))
1662 fprintf(out,
1663 "DEFINESET(OPENLIB)\n"
1664 "DEFINESET(CLOSELIB)\n"
1666 if (cfg->modtype == DEVICE)
1667 fprintf(out,
1668 "DEFINESET(OPENDEV)\n"
1669 "DEFINESET(CLOSEDEV)\n"
1671 if (cfg->classlist != NULL)
1672 fprintf(out,
1673 "DEFINESET(CLASSESINIT)\n"
1674 "DEFINESET(CLASSESEXPUNGE)\n"
1676 fprintf(out, "\n");