use a unique name for each modules get/setbase functions
[AROS.git] / tools / genmodule / writestart.c
blob5679379e9b1cc39e3e84ee8580726ee56c1fe486
1 /*
2 Copyright © 1995-2017, 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 LIBBASETYPEPTR __GM_GetParentPerTaskBase(void)\n"
269 "{\n"
270 " return (LIBBASETYPEPTR)GetParentTaskStorageSlot(__pertaskslot);\n"
271 "}\n"
272 "static inline void __GM_SetPerTaskBase(LIBBASETYPEPTR base)\n"
273 "{\n"
274 " SetTaskStorageSlot(__pertaskslot, (IPTR)base);\n"
275 "}\n"
280 /* Set the size of the library base to accomodate the relbases */
281 if (cfg->options & OPTION_DUPBASE)
283 fprintf(out,
284 "#define LIBBASESIZE (sizeof(struct __GM_DupBase) + sizeof(struct Library *)*%d)\n"
285 , slist_length(cfg->rellibs)
288 } else {
289 fprintf(out,
290 "#define LIBBASESIZE (sizeof(LIBBASETYPE) + sizeof(struct Library *)*%d)\n"
291 , slist_length(cfg->rellibs)
295 if (cfg->rellibs) {
296 struct stringlist *sl;
297 int i, n = slist_length(cfg->rellibs);
299 for (sl=cfg->rellibs; sl; sl=sl->next, n--) {
300 fprintf(out,
301 "#ifndef AROS_RELLIB_OFFSET_%s\n"
302 "# error '%s' is not a relative library\n"
303 "#endif\n"
304 "const IPTR AROS_RELLIB_OFFSET_%s = LIBBASESIZE-sizeof(struct Library *)*%d;\n"
305 , upname(sl->s)
306 , sl->s
307 , upname(sl->s)
313 if (cfg->options & OPTION_DUPBASE) {
314 fprintf(
315 out,
316 "static LONG __GM_BaseSlot;\n"
317 "char *__aros_getoffsettable_%s(void)\n"
318 "{\n"
319 " return (char *)GetTaskStorageSlot(__GM_BaseSlot);\n"
320 "}\n"
321 "void __aros_setoffsettable_%s(void *base)\n"
322 "{\n"
323 " SetTaskStorageSlot(__GM_BaseSlot, (IPTR)base);\n"
324 "}\n"
325 "%s__aros_getbase_%s(void)\n"
326 "{\n"
327 " return (%s)__aros_getoffsettable_%s();\n"
328 "}\n",
329 cfg->modulename, cfg->modulename,
330 cfg->libbasetypeptrextern, cfg->libbase,
331 cfg->libbasetypeptrextern, cfg->modulename
333 } else if (cfg->rellibs || (cfg->options & OPTION_STACKCALL)) {
334 fprintf(out,
335 "#ifdef __aros_getoffsettable_%s\n", cfg->modulename
337 if ((cfg->options & OPTION_STACKCALL))
338 fprintf(out,
339 "#error Redefining __aros_setoffsettable_%s is not permitted with stackcall APIs\n", cfg->modulename
341 else
342 fprintf(out,
343 "#define __aros_getbase_%s() __aros_getoffsettable_%s()\n",
344 cfg->libbase, cfg->modulename
346 fprintf(out,
347 "#else /* !__aros_getoffsettable */\n"
348 "static char *__GM_OffsetTable;\n"
349 "char *__aros_getoffsettable_%s(void)\n"
350 "{\n"
351 " return __GM_OffsetTable;\n"
352 "}\n"
353 "BOOL __aros_setoffsettable_%s(char *base)\n"
354 "{\n"
355 " __GM_OffsetTable = base;\n"
356 " return TRUE;\n"
357 "}\n"
358 "%s__aros_getbase_%s(void)\n"
359 "{\n"
360 " return (%s)__aros_getoffsettable_%s();\n"
361 "}\n"
362 "#endif /* __aros_getoffsettable */\n"
363 "\n",
364 cfg->modulename, cfg->modulename,
365 cfg->libbasetypeptrextern, cfg->libbase,
366 cfg->libbasetypeptrextern, cfg->modulename
370 if (cfg->rellibs)
372 struct stringlist *sl;
374 for (sl = cfg->rellibs; sl; sl = sl->next)
376 fprintf(out,
377 "AROS_IMPORT_ASM_SYM(void *,__GM_rellib_base_%s,AROS_RELLIB_BASE_%s);\n"
378 , sl->s
379 , upname(sl->s)
384 for (classlistit = cfg->classlist; classlistit != NULL; classlistit = classlistit->next)
386 /* For the main class basename is the same as the module basename */
387 if (strcmp(classlistit->basename, cfg->basename) == 0)
389 if (classlistit->classptr_var == NULL)
391 fprintf(out,
392 "#if !defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
393 "static APTR GM_UNIQUENAME(%sClass);\n"
394 "#define GM_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
395 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
396 "#define %s_STORE_CLASSPTR 1\n"
397 "#elif defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
398 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_CLASSPTR_FIELD(LIBBASE))\n"
399 "#elif !defined(GM_CLASSPTR_FIELD) && defined(%s_CLASSPTR_FIELD)\n"
400 "#define GM_CLASSPTR_FIELD(LIBBASE) (%s_CLASSPTR_FIELD(LIBBASE))\n"
401 "#endif\n",
402 classlistit->basename,
403 classlistit->basename,
404 classlistit->basename,
405 classlistit->basename, classlistit->basename,
406 classlistit->basename,
407 classlistit->basename,
408 classlistit->basename,
409 classlistit->basename,
410 classlistit->basename
413 else
415 fprintf(out,
416 "#define GM_CLASSPTR_FIELD(LIBBASE) (%s)\n"
417 "#define %s_CLASSPTR_FIELD(LIBBASE) (%s)\n"
418 "#define %s_STORE_CLASSPTR 1\n",
419 classlistit->classptr_var,
420 classlistit->basename, classlistit->classptr_var,
421 classlistit->basename
425 else
427 if (classlistit->classptr_var == NULL)
429 fprintf(out,
430 "#if !defined(%s_CLASSPTR_FIELD)\n"
431 "static APTR GM_UNIQUENAME(%sClass);\n"
432 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
433 "#define %s_STORE_CLASSPTR 1\n"
434 "#endif\n",
435 classlistit->basename,
436 classlistit->basename,
437 classlistit->basename, classlistit->basename,
438 classlistit->basename
441 else
443 fprintf(out,
444 "#define %s_CLASSPTR_FIELD(LIBBASE) (%s)\n"
445 "#define %s_STORE_CLASSPTR 1\n",
446 classlistit->basename, classlistit->classptr_var,
447 classlistit->basename
453 /* Write out the defines for the functions of the function table */
454 writefuncdefs(out, cfg, cfg->funclist);
455 /* Write internal stubs */
456 writefuncinternalstubs(out, cfg, cfg->funclist);
457 fprintf(out, "\n");
460 /* Write out the includes needed for the classes */
461 if (cfg->classlist != NULL)
462 writeboopsiincludes(out);
464 for (classlistit = cfg->classlist; classlistit != NULL; classlistit = classlistit->next)
466 switch (classlistit->classtype)
468 case MUI:
469 case MCC:
470 case MCP:
471 if (!muiinc)
473 writemuiincludes(out);
474 muiinc = 1;
476 /* Fall through: also write boopsi includes */
477 case GADGET:
478 case DATATYPE:
479 case CLASS:
480 case IMAGE:
481 if (!boopsiinc)
483 writeboopsiincludes(out);
484 boopsiinc = 1;
486 break;
487 case HIDD:
488 if (!oopinc)
490 writeoopincludes(out);
491 oopinc = 1;
493 break;
494 default:
495 fprintf(stderr, "Internal error: unhandled classtype in writedecl\n");
496 exit(20);
502 static void writedeclsets(FILE *out, struct config *cfg)
504 /* PROGRAM_ENTRIES is marked as handled but are just ignored in modules */
505 fprintf(out,
506 "THIS_PROGRAM_HANDLES_SYMBOLSET(INIT)\n"
507 "THIS_PROGRAM_HANDLES_SYMBOLSET(EXIT)\n"
508 "DECLARESET(INIT)\n"
509 "DECLARESET(EXIT)\n"
510 "THIS_PROGRAM_HANDLES_SYMBOLSET(PROGRAM_ENTRIES)\n"
511 "DECLARESET(PROGRAM_ENTRIES)\n"
513 if (cfg->modtype != HANDLER)
514 fprintf(out,
515 "THIS_PROGRAM_HANDLES_SYMBOLSET(CTORS)\n"
516 "THIS_PROGRAM_HANDLES_SYMBOLSET(DTORS)\n"
517 "DECLARESET(CTORS)\n"
518 "DECLARESET(DTORS)\n"
519 "THIS_PROGRAM_HANDLES_SYMBOLSET(INIT_ARRAY)\n"
520 "THIS_PROGRAM_HANDLES_SYMBOLSET(FINI_ARRAY)\n"
521 "DECLARESET(INIT_ARRAY)\n"
522 "DECLARESET(FINI_ARRAY)\n"
523 "THIS_PROGRAM_HANDLES_SYMBOLSET(INITLIB)\n"
524 "THIS_PROGRAM_HANDLES_SYMBOLSET(EXPUNGELIB)\n"
525 "DECLARESET(INITLIB)\n"
526 "DECLARESET(EXPUNGELIB)\n"
528 if (!(cfg->options & OPTION_NOAUTOLIB))
530 fprintf(out,
531 "THIS_PROGRAM_HANDLES_SYMBOLSET(LIBS)\n"
532 "DECLARESET(LIBS)\n"
534 if (cfg->rellibs)
535 fprintf(out,
536 "THIS_PROGRAM_HANDLES_SYMBOLSET(RELLIBS)\n"
537 "DECLARESET(RELLIBS)\n"
540 if (!(cfg->options & OPTION_NOOPENCLOSE))
541 fprintf(out,
542 "THIS_PROGRAM_HANDLES_SYMBOLSET(OPENLIB)\n"
543 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLOSELIB)\n"
544 "DECLARESET(OPENLIB)\n"
545 "DECLARESET(CLOSELIB)\n"
547 if (cfg->modtype == DEVICE)
548 fprintf(out,
549 "THIS_PROGRAM_HANDLES_SYMBOLSET(OPENDEV)\n"
550 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLOSEDEV)\n"
551 "DECLARESET(OPENDEV)\n"
552 "DECLARESET(CLOSEDEV)\n"
554 if (cfg->classlist != NULL)
555 fprintf(out,
556 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLASSESINIT)\n"
557 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLASSESEXPUNGE)\n"
558 "DECLARESET(CLASSESINIT)\n"
559 "DECLARESET(CLASSESEXPUNGE)\n"
560 "#define ADD2INITCLASSES(symbol, pri) ADD2SET(symbol, CLASSESINIT, pri)\n"
561 "#define ADD2EXPUNGECLASSES(symbol, pri) ADD2SET(symbol, CLASSESEXPUNGE, pri)\n"
563 fprintf(out, "\n");
567 static void writeresident(FILE *out, struct config *cfg)
569 char *rt_skip = cfg->addromtag;
571 if (rt_skip)
572 fprintf(out, "extern const struct Resident %s;\n", rt_skip);
573 else
575 rt_skip = "GM_UNIQUENAME(End)";
576 fprintf(out, "extern int %s(void);\n", rt_skip);
578 fprintf(out,
579 "extern const APTR GM_UNIQUENAME(FuncTable)[];\n"
581 if (cfg->options & OPTION_RESAUTOINIT)
582 fprintf(out, "static const struct InitTable GM_UNIQUENAME(InitTable);\n");
583 fprintf(out,
584 "\n"
585 "extern const char GM_UNIQUENAME(LibName)[];\n"
586 "extern const char GM_UNIQUENAME(LibID)[];\n"
587 "extern const char GM_UNIQUENAME(Copyright)[];\n"
588 "\n"
591 if (cfg->options & OPTION_RESAUTOINIT)
593 fprintf(out,
594 "#define __freebase(LIBBASE)\\\n"
595 "do {\\\n"
596 " UWORD negsize, possize;\\\n"
597 " UBYTE *negptr = (UBYTE *)LIBBASE;\\\n"
598 " negsize = ((struct Library *)LIBBASE)->lib_NegSize;\\\n"
599 " negptr -= negsize;\\\n"
600 " possize = ((struct Library *)LIBBASE)->lib_PosSize;\\\n"
601 " FreeMem (negptr, negsize+possize);\\\n"
602 "} while(0)\n"
603 "\n");
606 fprintf(out,
607 "AROS_UFP3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
608 " AROS_UFPA(LIBBASETYPEPTR, LIBBASE, D0),\n"
609 " AROS_UFPA(BPTR, segList, A0),\n"
610 " AROS_UFPA(struct ExecBase *, sysBase, A6)\n"
611 ");\n"
613 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
615 fprintf(out,
616 "AROS_LD1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
617 " AROS_LDA(LIBBASETYPEPTR, extralh, D0),\n"
618 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
619 ");\n"
620 "\n",
621 cfg->basename
624 fprintf(out,
625 "__section(\".text.romtag\") struct Resident const GM_UNIQUENAME(ROMTag) =\n"
626 "{\n"
627 " RTC_MATCHWORD,\n"
628 " (struct Resident *)&GM_UNIQUENAME(ROMTag),\n"
629 " (APTR)&%s,\n"
630 " RESIDENTFLAGS,\n"
631 " VERSION_NUMBER,\n",
632 rt_skip
634 switch (cfg->modtype)
636 case LIBRARY:
637 case MUI:
638 case MCC:
639 case MCP:
640 case GADGET:
641 case DATATYPE:
642 case USBCLASS:
643 case HIDD:
644 fprintf(out, " NT_LIBRARY,\n");
645 break;
646 case DEVICE:
647 fprintf(out, " NT_DEVICE,\n");
648 break;
649 case RESOURCE:
650 case HANDLER:
651 fprintf(out, " NT_RESOURCE,\n");
652 break;
653 default:
654 fprintf(stderr, "Internal error: unsupported modtype for NT_...\n");
655 exit(20);
656 break;
658 fprintf(out,
659 " RESIDENTPRI,\n"
660 " (CONST_STRPTR)&GM_UNIQUENAME(LibName)[0],\n"
661 " (CONST_STRPTR)&GM_UNIQUENAME(LibID)[6],\n"
663 if (cfg->options & OPTION_RESAUTOINIT)
665 fprintf(out,
666 " (APTR)&GM_UNIQUENAME(InitTable)\n"
667 "};\n"
668 "\n"
669 "__section(\".text.romtag\") static struct InitTable\n"
670 "{\n"
671 " IPTR Size;\n"
672 " const APTR *FuncTable;\n"
673 " struct DataTable *DataTable;\n"
674 " APTR InitLibTable;\n"
675 "}\n"
676 "const GM_UNIQUENAME(InitTable) =\n"
677 "{\n"
678 " LIBBASESIZE,\n"
679 " &GM_UNIQUENAME(FuncTable)[0],\n"
680 " NULL,\n"
681 " (APTR)GM_UNIQUENAME(InitLib)\n"
682 "};\n"
685 else
686 fprintf(out, " (APTR)GM_UNIQUENAME(InitLib)\n};\n");
688 fprintf(out,
689 "\n"
690 "__section(\".text.romtag\") const char GM_UNIQUENAME(LibName)[] = MOD_NAME_STRING;\n"
691 "__section(\".text.romtag\") const char GM_UNIQUENAME(LibID)[] = VERSION_STRING;\n"
692 "__section(\".text.romtag\") const char GM_UNIQUENAME(Copyright)[] = COPYRIGHT_STRING;\n"
693 "\n"
697 static void writehandler(FILE *out, struct config *cfg)
699 int i, handlers=0;
700 struct handlerinfo *hl;
701 int need_fse = 0, need_dos = 0;
703 fprintf(out,
704 "\n"
705 "#include <resources/filesysres.h>\n"
706 "#include <aros/system.h>\n"
707 "#include <proto/arossupport.h>\n"
708 "#include <proto/expansion.h>\n"
709 "\n"
712 for (hl = cfg->handlerlist; hl != NULL; hl = hl->next) {
713 if (hl->type == HANDLER_DOSNODE)
714 need_dos = 1;
715 else
716 need_fse = 1;
717 handlers++;
720 fprintf(out,
721 "\n"
722 "LONG %s(struct ExecBase *sysBase);\n"
723 "extern const LONG __aros_libreq_SysBase __attribute__((weak));\n"
724 "\n"
725 "__startup AROS_PROCH(GM_UNIQUENAME(Handler), argptr, argsize, SysBase)\n"
726 "{\n"
727 " AROS_PROCFUNC_INIT\n"
728 "\n"
729 " LONG ret = RETURN_FAIL;\n"
730 "\n"
731 " if (!SysBase || SysBase->LibNode.lib_Version < __aros_libreq_SysBase)\n"
732 " return ERROR_INVALID_RESIDENT_LIBRARY;\n"
733 " if (set_call_funcs(SETNAME(INIT), 1, 1)) {\n"
734 " ret = %s(SysBase);\n"
735 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
736 " }\n"
737 "\n"
738 " return ret;\n"
739 "\n"
740 " AROS_PROCFUNC_EXIT\n"
741 "}\n"
742 , cfg->handlerfunc
743 , cfg->handlerfunc
746 fprintf(out,
747 "\n"
748 "static inline BOOL GM_UNIQUENAME(InitHandler)(struct ExecBase *SysBase)\n"
749 "{\n"
752 if (!need_dos && !need_fse) {
753 fprintf(out,
754 " return TRUE;\n"
755 "}\n"
757 return;
760 fprintf(out,
761 " BPTR seg;\n"
764 if (need_dos) {
765 fprintf(out,
766 " struct Library *ExpansionBase;\n"
769 if (need_fse) {
770 fprintf(out,
771 " struct FileSysResource *fsr;\n"
772 " struct FileSysEntry *fse;\n"
775 if (need_fse) {
776 fprintf(out,
777 " fsr = (struct FileSysResource *)OpenResource(\"FileSystem.resource\");\n"
778 " if (fsr == NULL)\n"
779 " return FALSE;\n"
782 if (need_dos) {
783 fprintf(out,
784 " ExpansionBase = OpenLibrary(\"expansion.library\", 36);\n"
785 " if (ExpansionBase == NULL)\n"
786 " return FALSE;\n"
789 fprintf(out,
790 " seg = CreateSegList(GM_UNIQUENAME(Handler));\n"
791 " if (seg != BNULL) {\n"
793 for (hl = cfg->handlerlist; hl != NULL; hl = hl->next)
795 switch (hl->type)
797 case HANDLER_DOSNODE:
798 fprintf(out,
799 "\n"
800 " {\n"
801 " struct DeviceNode *node;\n"
802 " IPTR pp[] = { \n"
803 " (IPTR)\"%s\",\n"
804 " (IPTR)NULL,\n"
805 " (IPTR)0,\n"
806 " (IPTR)0,\n"
807 " (IPTR)0\n"
808 " };\n"
809 " node = MakeDosNode((APTR)pp);\n"
810 " if (node) {\n"
811 " node->dn_StackSize = %u;\n"
812 " node->dn_SegList = seg;\n"
813 " node->dn_Startup = (BPTR)%d;\n"
814 " node->dn_Priority = %d;\n"
815 " node->dn_GlobalVec = (BPTR)(SIPTR)-1;\n"
816 " AddBootNode(%d, 0, node, NULL);\n"
817 " }\n"
818 " }\n"
819 "\n"
820 , hl->name
821 , hl->stacksize
822 , hl->startup
823 , hl->priority
824 , hl->bootpri
826 break;
827 case HANDLER_RESIDENT:
828 case HANDLER_DOSTYPE:
829 fprintf(out,
830 "\n"
831 " /* Check to see if we can allocate the memory for the fse */\n"
832 " fse = AllocMem(sizeof(*fse), MEMF_CLEAR);\n"
833 " if (fse) {\n"
834 " fse->fse_Node.ln_Name = VERSION_STRING;\n"
835 " fse->fse_Node.ln_Pri = %d;\n"
836 " fse->fse_DosType = 0x%08x;\n"
837 " fse->fse_Version = (MAJOR_VERSION << 16) | MINOR_VERSION;\n"
838 " fse->fse_PatchFlags = FSEF_SEGLIST | FSEF_GLOBALVEC | FSEF_PRIORITY;\n"
839 , hl->autodetect
840 , hl->id
842 if (hl->stacksize)
844 fprintf(out,
845 " fse->fse_PatchFlags |= FSEF_STACKSIZE;\n"
846 " fse->fse_StackSize = %d;\n"
847 , hl->stacksize
850 if (hl->name)
851 fprintf(out,
852 " fse->fse_PatchFlags |= FSEF_HANDLER;\n"
853 " fse->fse_Handler = AROS_CONST_BSTR(\"%s\");\n"
854 , hl->name);
855 fprintf(out,
856 " fse->fse_Priority = %d;\n"
857 " fse->fse_SegList = seg;\n"
858 " fse->fse_GlobalVec = (BPTR)(SIPTR)-1;\n"
859 " fse->fse_Startup = (BPTR)%d;\n"
860 "\n"
861 " /* Add to the list. I know forbid and permit are\n"
862 " * a little unnecessary for the pre-multitasking state\n"
863 " * we should be in at this point, but you never know\n"
864 " * who's going to blindly copy this code as an example.\n"
865 " */\n"
866 " Forbid();\n"
867 " Enqueue(&fsr->fsr_FileSysEntries, (struct Node *)fse);\n"
868 " Permit();\n"
869 " }\n"
870 , hl->priority
871 , hl->startup
873 break;
876 fprintf(out,
877 " }\n"
879 if (need_dos) {
880 fprintf(out,
881 " CloseLibrary(ExpansionBase);\n"
884 fprintf(out,
885 " return TRUE;\n"
886 "}\n"
887 "\n"
891 static void writeinitlib(FILE *out, struct config *cfg)
893 if (cfg->handlerlist)
894 writehandler(out, cfg);
896 fprintf(out,
897 "extern const LONG __aros_libreq_SysBase __attribute__((weak));\n"
898 "\n"
899 "AROS_UFH3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
900 " AROS_UFHA(LIBBASETYPEPTR, LIBBASE, D0),\n"
901 " AROS_UFHA(BPTR, segList, A0),\n"
902 " AROS_UFHA(struct ExecBase *, sysBase, A6)\n"
903 ")\n"
904 "{\n"
905 " AROS_USERFUNC_INIT\n"
908 if (cfg->modtype == HANDLER) {
909 fprintf(out,
910 "\n"
911 " GM_UNIQUENAME(InitHandler)(sysBase);\n"
912 " return LIBBASE;\n"
913 "\n"
914 " AROS_USERFUNC_EXIT\n"
915 "}\n"
916 "\n"
918 return;
921 fprintf(out,
922 "\n"
923 " int ok;\n"
924 " int initcalled = 0;\n"
926 /* Set the global SysBase, needed for __aros_setoffsettable()/__aros_getoffsettable() */
927 if (cfg->options & OPTION_DUPBASE)
928 fprintf(out,
929 " SysBase = sysBase;\n"
931 else
932 fprintf(out,
933 " struct ExecBase *SysBase = sysBase;\n"
935 fprintf(out,
936 "\n"
937 "#ifdef GM_SYSBASE_FIELD\n"
938 " GM_SYSBASE_FIELD(LIBBASE) = (APTR)SysBase;\n"
939 "#endif\n"
940 " if (!SysBase || SysBase->LibNode.lib_Version < __aros_libreq_SysBase)\n"
941 " return NULL;\n"
942 "\n"
945 if (cfg->options & OPTION_RESAUTOINIT) {
946 fprintf(out,
947 "#ifdef GM_OOPBASE_FIELD\n"
948 " GM_OOPBASE_FIELD(LIBBASE) = OpenLibrary(\"oop.library\",0);\n"
949 " if (GM_OOPBASE_FIELD(LIBBASE) == NULL)\n"
950 " return NULL;\n"
951 "#endif\n"
955 if (!(cfg->options & OPTION_RESAUTOINIT))
957 fprintf(out,
958 " int vecsize;\n"
959 " struct Node *n;\n"
960 " char *mem;\n"
961 "\n"
962 " vecsize = FUNCTIONS_COUNT * LIB_VECTSIZE;\n"
963 " if (vecsize > 0)\n"
964 " vecsize = ((vecsize-1)/sizeof(IPTR) + 1)*sizeof(IPTR);\n"
965 " mem = AllocMem(vecsize+sizeof(LIBBASETYPE), MEMF_PUBLIC|MEMF_CLEAR);\n"
966 " if (mem == NULL)\n"
967 " return NULL;\n"
968 " LIBBASE = (LIBBASETYPEPTR)(mem + vecsize);\n"
969 " n = (struct Node *)LIBBASE;\n"
970 " n->ln_Type = NT_RESOURCE;\n"
971 " n->ln_Pri = RESIDENTPRI;\n"
972 " n->ln_Name = (char *)GM_UNIQUENAME(LibName);\n"
973 " MakeFunctions(LIBBASE, (APTR)GM_UNIQUENAME(FuncTable), NULL);\n"
975 if ((cfg->modtype != RESOURCE) && (cfg->options & OPTION_SELFINIT))
977 fprintf(out,
978 " ((struct Library*)LIBBASE)->lib_NegSize = vecsize;\n"
979 " ((struct Library*)LIBBASE)->lib_PosSize = sizeof(LIBBASETYPE);\n"
984 else
986 fprintf(out,
987 " ((struct Library *)LIBBASE)->lib_Revision = REVISION_NUMBER;\n"
991 if (cfg->options & OPTION_DUPBASE)
992 fprintf(out,
993 " __GM_BaseSlot = AllocTaskStorageSlot();\n"
994 " if (!SetTaskStorageSlot(__GM_BaseSlot, (IPTR)LIBBASE)) {\n"
995 " FreeTaskStorageSlot(__GM_BaseSlot);\n"
996 " return NULL;\n"
997 " }\n"
999 else if (cfg->rellibs || (cfg->options & OPTION_STACKCALL))
1000 fprintf(out,
1001 " __aros_setoffsettable_%s((char *)LIBBASE);\n", cfg->modulename
1003 if (cfg->options & OPTION_PERTASKBASE)
1004 fprintf(out,
1005 " __pertaskslot = AllocTaskStorageSlot();\n"
1008 if (!(cfg->options & OPTION_NOEXPUNGE) && cfg->modtype!=RESOURCE)
1009 fprintf(out, " GM_SEGLIST_FIELD(LIBBASE) = segList;\n");
1010 if (cfg->options & OPTION_DUPBASE)
1011 fprintf(out, " GM_ROOTBASE_FIELD(LIBBASE) = (LIBBASETYPEPTR)LIBBASE;\n");
1012 fprintf(out, " if (");
1013 if (!(cfg->options & OPTION_NOAUTOLIB))
1014 fprintf(out, "set_open_libraries() && ");
1015 if (cfg->rellibs)
1016 fprintf(out, "set_open_rellibraries(LIBBASE) && ");
1017 fprintf(out,
1018 "set_call_funcs(SETNAME(INIT), 1, 1) &&"
1020 if (cfg->classlist != NULL)
1021 fprintf(out, "set_call_libfuncs(SETNAME(CLASSESINIT), 1, 1, LIBBASE) && ");
1022 fprintf(out,
1023 "1)\n"
1024 " {\n"
1025 " set_call_funcs(SETNAME(CTORS), -1, 0);\n"
1026 " set_call_funcs(SETNAME(INIT_ARRAY), 1, 0);\n"
1027 "\n"
1030 fprintf(out,
1031 " initcalled = 1;\n"
1032 " ok = set_call_libfuncs(SETNAME(INITLIB), 1, 1, LIBBASE);\n"
1033 " }\n"
1034 " else\n"
1035 " ok = 0;\n"
1036 "\n"
1037 " if (!ok)\n"
1038 " {\n"
1039 " if (initcalled)\n"
1040 " set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 0, LIBBASE);\n"
1041 " set_call_funcs(SETNAME(FINI_ARRAY), -1, 0);\n"
1042 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
1043 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
1045 if (cfg->classlist != NULL)
1046 fprintf(out, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, LIBBASE);\n");
1047 if (cfg->rellibs)
1048 fprintf(out, " set_close_rellibraries(LIBBASE);\n");
1049 if (!(cfg->options & OPTION_NOAUTOLIB))
1050 fprintf(out, " set_close_libraries();\n");
1052 if (cfg->options & OPTION_RESAUTOINIT)
1054 fprintf(out,
1055 "\n"
1056 " __freebase(LIBBASE);\n"
1059 else
1061 fprintf(out,
1062 "\n"
1063 " FreeMem(mem, vecsize+LIBBASESIZE);\n"
1066 fprintf(out,
1067 " return NULL;\n"
1068 " }\n"
1069 " else\n"
1070 " {\n"
1073 if (!(cfg->options & OPTION_RESAUTOINIT) && !(cfg->options & OPTION_SELFINIT))
1075 switch (cfg->modtype)
1077 case RESOURCE:
1078 fprintf(out, " AddResource(LIBBASE);\n");
1079 break;
1081 case DEVICE:
1082 fprintf(out, " AddDevice(LIBBASE);\n");
1084 default:
1085 /* Everything else is library */
1086 fprintf(out, " AddLibrary(LIBBASE);\n");
1087 break;
1091 fprintf(out,
1092 " return LIBBASE;\n"
1093 " }\n"
1094 "\n"
1095 " AROS_USERFUNC_EXIT\n"
1096 "}\n"
1097 "\n"
1101 static void writeopenlib(FILE *out, struct config *cfg)
1103 switch (cfg->modtype)
1105 case RESOURCE:
1106 fprintf(stderr, "Internal error: writeopenlib called for a resource\n");
1107 break;
1108 case HANDLER:
1109 fprintf(stderr, "Internal error: writeopenlib called for a handler\n");
1110 break;
1111 case DEVICE:
1112 if (cfg->options & OPTION_NOOPENCLOSE)
1113 fprintf(out,
1114 "AROS_LD3 (void, GM_UNIQUENAME(OpenLib),\n"
1115 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1116 " AROS_LDA(ULONG, unitnum, D0),\n"
1117 " AROS_LDA(ULONG, flags, D1),\n"
1118 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1119 ");\n",
1120 cfg->basename
1122 else
1124 fprintf(out,
1125 "AROS_LH3 (void, GM_UNIQUENAME(OpenLib),\n"
1126 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1127 " AROS_LHA(IPTR, unitnum, D0),\n"
1128 " AROS_LHA(ULONG, flags, D1),\n"
1129 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1130 ")\n",
1131 cfg->basename
1133 fprintf(out,
1134 "{\n"
1135 " AROS_LIBFUNC_INIT\n"
1136 "\n"
1137 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, LIBBASE)\n"
1138 " && set_call_devfuncs(SETNAME(OPENDEV), 1, 1, LIBBASE, ioreq, unitnum, flags)\n"
1139 " )\n"
1140 " {\n"
1141 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1142 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1143 "\n"
1144 " ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;\n"
1145 " }\n"
1146 " else\n"
1147 " {\n"
1148 " if (ioreq->io_Error >= 0)\n"
1149 " ioreq->io_Error = IOERR_OPENFAIL;\n"
1150 " }\n"
1151 "\n"
1152 " return;\n"
1153 "\n"
1154 " AROS_LIBFUNC_EXIT\n"
1155 "}\n"
1156 "\n"
1159 break;
1160 default:
1161 if (cfg->options & OPTION_NOOPENCLOSE)
1163 fprintf(out,
1164 "AROS_LD1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
1165 " AROS_LDA (ULONG, version, D0),\n"
1166 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1167 ");\n",
1168 cfg->basename
1170 return;
1172 fprintf(out,
1173 "AROS_LH1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
1174 " AROS_LHA (ULONG, version, D0),\n"
1175 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1176 ")\n"
1177 "{\n"
1178 " AROS_LIBFUNC_INIT\n"
1179 "\n",
1180 cfg->basename
1182 if (!(cfg->options & OPTION_DUPBASE))
1184 fprintf(out,
1185 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, LIBBASE) )\n"
1186 " {\n"
1187 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1188 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1189 " return LIBBASE;\n"
1190 " }\n"
1191 "\n"
1192 " return NULL;\n"
1193 "\n"
1194 " AROS_LIBFUNC_EXIT\n"
1195 "}\n"
1196 "\n"
1199 else /* OPTION_DUPBASE */
1201 fprintf(out,
1202 " struct Library *newlib = NULL;\n"
1203 " UWORD possize = ((struct Library *)LIBBASE)->lib_PosSize;\n"
1204 " LIBBASETYPEPTR oldbase = (LIBBASETYPEPTR)__aros_getbase_%s();\n",
1205 cfg->libbase
1207 if (cfg->options & OPTION_PERTASKBASE)
1208 fprintf(out,
1209 " struct Task *thistask = FindTask(NULL);\n"
1210 " LIBBASETYPEPTR oldpertaskbase = __GM_GetPerTaskBase();\n"
1211 " if (!oldpertaskbase)\n"
1212 " oldpertaskbase = __GM_GetParentPerTaskBase();\n"
1213 " newlib = (struct Library *)oldpertaskbase;\n"
1214 " if (newlib)\n"
1215 " {\n"
1216 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1217 " if (dupbase->task != thistask)\n"
1218 " newlib = NULL;\n"
1219 " else if (thistask->tc_Node.ln_Type == NT_PROCESS\n"
1220 " && dupbase->retaddr != ((struct Process *)thistask)->pr_ReturnAddr\n"
1221 " )\n"
1222 " newlib = NULL;\n"
1223 " else\n"
1224 " dupbase->taskopencount++;\n"
1225 " }\n"
1228 fprintf(out,
1229 "\n"
1230 " if (newlib == NULL)\n"
1231 " {\n"
1232 " newlib = MakeLibrary(GM_UNIQUENAME(InitTable).FuncTable,\n"
1233 " GM_UNIQUENAME(InitTable).DataTable,\n"
1234 " NULL,\n"
1235 " GM_UNIQUENAME(InitTable).Size,\n"
1236 " (BPTR)NULL\n"
1237 " );\n"
1238 " if (newlib == NULL)\n"
1239 " return NULL;\n"
1240 "\n"
1241 " CopyMem(LIBBASE, newlib, possize);\n"
1242 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1243 " dupbase->oldbase = oldbase;\n"
1244 " __aros_setoffsettable_%s((char *)newlib);\n",
1245 cfg->modulename
1247 if (cfg->options & OPTION_PERTASKBASE)
1248 fprintf(out,
1249 " dupbase->task = thistask;\n"
1250 " if (thistask->tc_Node.ln_Type == NT_PROCESS)\n"
1251 " dupbase->retaddr = ((struct Process *)thistask)->pr_ReturnAddr;\n"
1252 " dupbase->oldpertaskbase = oldpertaskbase;\n"
1253 " dupbase->taskopencount = 1;\n"
1254 " __GM_SetPerTaskBase((LIBBASETYPEPTR)newlib);\n"
1256 fprintf(out,
1257 "\n"
1258 " if (!(set_open_rellibraries(newlib)\n"
1259 " && set_call_libfuncs(SETNAME(OPENLIB), 1, 1, newlib)\n"
1260 " )\n"
1261 " )\n"
1262 " {\n");
1263 if (cfg->options & OPTION_PERTASKBASE)
1264 fprintf(out,
1265 " __GM_SetPerTaskBase(oldpertaskbase);\n");
1266 fprintf(out,
1267 " __freebase(newlib);\n"
1268 " return NULL;\n"
1269 " }\n"
1270 "\n"
1271 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1272 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1273 " }\n"
1274 "\n"
1275 " return (LIBBASETYPEPTR)newlib;\n"
1276 "\n"
1277 " AROS_LIBFUNC_EXIT\n"
1278 "}\n"
1279 "\n"
1286 static void writecloselib(FILE *out, struct config *cfg)
1288 if (cfg->options & OPTION_NOOPENCLOSE)
1290 if (cfg->modtype != DEVICE)
1291 fprintf(out,
1292 "AROS_LD0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1293 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1294 ");\n",
1295 cfg->basename
1297 else
1298 fprintf(out,
1299 "AROS_LD1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1300 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1301 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1302 ");\n",
1303 cfg->basename
1305 return;
1307 if (cfg->modtype != DEVICE)
1308 fprintf(out,
1309 "AROS_LH0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1310 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1311 ")\n",
1312 cfg->basename
1314 else
1315 fprintf(out,
1316 "AROS_LH1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1317 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1318 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1319 ")\n",
1320 cfg->basename
1323 fprintf(out,
1324 "{\n"
1325 " AROS_LIBFUNC_INIT\n"
1326 "\n"
1328 if (cfg->modtype == DEVICE)
1329 fprintf(out,
1330 " if (!set_call_devfuncs(SETNAME(CLOSEDEV), -1, 1, LIBBASE, ioreq, 0, 0))\n"
1331 " {\n"
1332 " return BNULL;\n"
1333 " }\n"
1335 if (!(cfg->options & OPTION_DUPBASE))
1337 fprintf(out,
1338 " ((struct Library *)LIBBASE)->lib_OpenCnt--;\n"
1339 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, LIBBASE);\n"
1342 else /* OPTION_DUPBASE */
1344 fprintf(out,
1345 " LIBBASETYPEPTR rootbase = GM_ROOTBASE_FIELD(LIBBASE);\n"
1346 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)LIBBASE;\n"
1347 " __aros_setoffsettable_%s(LIBBASE);\n",
1348 cfg->modulename
1350 if (cfg->options & OPTION_PERTASKBASE)
1351 fprintf(out,
1352 " dupbase->taskopencount--;\n"
1353 " if (dupbase->taskopencount != 0)\n"
1354 " return BNULL;\n"
1356 fprintf(out,
1357 "\n"
1358 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, LIBBASE);\n"
1359 " set_close_rellibraries(LIBBASE);\n"
1360 " __aros_setoffsettable_%s((char *)dupbase->oldbase);\n",
1361 cfg->modulename
1363 if (cfg->options & OPTION_PERTASKBASE)
1364 fprintf(out,
1365 " __GM_SetPerTaskBase(((struct __GM_DupBase *)LIBBASE)->oldpertaskbase);\n"
1367 fprintf(out,
1368 " __freebase(LIBBASE);\n"
1369 " LIBBASE = rootbase;\n"
1370 " ((struct Library *)LIBBASE)->lib_OpenCnt--;\n"
1371 "\n"
1374 if (!(cfg->options & OPTION_NOEXPUNGE))
1375 fprintf(out,
1376 " if\n"
1377 " (\n"
1378 " (((struct Library *)LIBBASE)->lib_OpenCnt == 0)\n"
1379 " && (((struct Library *)LIBBASE)->lib_Flags & LIBF_DELEXP)\n"
1380 " )\n"
1381 " {\n"
1382 " return AROS_LC1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1383 " AROS_LCA(LIBBASETYPEPTR, LIBBASE, D0),\n"
1384 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
1385 " );\n"
1386 " }\n",
1387 cfg->basename
1389 fprintf(out,
1390 "\n"
1391 " return BNULL;\n"
1392 "\n"
1393 " AROS_LIBFUNC_EXIT\n"
1394 "}\n"
1395 "\n"
1400 static void writeexpungelib(FILE *out, struct config *cfg)
1402 fprintf(out,
1403 "AROS_LH1 (BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1404 " AROS_LHA(LIBBASETYPEPTR, extralh, D0),\n"
1405 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
1406 ")\n",
1407 cfg->basename
1409 fprintf(out,
1410 "{\n"
1411 " AROS_LIBFUNC_INIT\n"
1412 "\n"
1414 if (!(cfg->options & OPTION_NOEXPUNGE))
1416 if (cfg->options & OPTION_RESAUTOINIT) {
1417 fprintf(out,
1418 "#ifdef GM_SYSBASE_FIELD\n"
1419 " struct ExecBase *SysBase = (struct ExecBase *)GM_SYSBASE_FIELD(LIBBASE);\n"
1420 "#endif\n"
1423 if (cfg->options & OPTION_DUPBASE)
1424 fprintf(out, " __aros_setoffsettable_%s(LIBBASE);\n", cfg->modulename);
1425 fprintf(out,
1426 "\n"
1427 " if ( ((struct Library *)LIBBASE)->lib_OpenCnt == 0 )\n"
1428 " {\n"
1429 " BPTR seglist = GM_SEGLIST_FIELD(LIBBASE);\n"
1430 "\n"
1431 " if(!set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 1, LIBBASE))\n"
1432 " {\n"
1433 " ((struct Library *)LIBBASE)->lib_Flags |= LIBF_DELEXP;\n"
1434 " return BNULL;\n"
1435 " }\n"
1436 "\n"
1437 " Remove((struct Node *)LIBBASE);\n"
1438 "\n"
1439 " set_call_funcs(SETNAME(FINI_ARRAY), -1, 0);\n"
1440 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
1441 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
1443 if (cfg->classlist != NULL)
1444 fprintf(out, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, LIBBASE);\n");
1445 if (cfg->rellibs)
1446 fprintf(out, " set_close_rellibraries(LIBBASE);\n");
1447 if (!(cfg->options & OPTION_NOAUTOLIB))
1448 fprintf(out, " set_close_libraries();\n"
1449 "#ifdef GM_OOPBASE_FIELD\n"
1450 " CloseLibrary((struct Library *)GM_OOPBASE_FIELD(LIBBASE));\n"
1451 "#endif\n"
1453 if (cfg->options & OPTION_PERTASKBASE)
1454 fprintf(out,
1455 " FreeTaskStorageSlot(__pertaskslot);\n"
1456 " __pertaskslot = 0;\n"
1458 fprintf(out,
1459 "\n"
1460 " __freebase(LIBBASE);\n"
1461 "\n"
1462 " return seglist;\n"
1463 " }\n"
1464 "\n"
1465 " ((struct Library *)LIBBASE)->lib_Flags |= LIBF_DELEXP;\n"
1468 fprintf(out,
1469 "\n"
1470 " return BNULL;\n"
1471 "\n"
1472 " AROS_LIBFUNC_EXIT\n"
1473 "}\n"
1474 "\n"
1479 static void writeextfunclib(FILE *out, struct config *cfg)
1481 fprintf(out,
1482 "AROS_LH0 (LIBBASETYPEPTR, GM_UNIQUENAME(ExtFuncLib),\n"
1483 " LIBBASETYPEPTR, LIBBASE, 4, %s\n"
1484 ")\n"
1485 "{\n"
1486 " AROS_LIBFUNC_INIT\n"
1487 " return NULL;\n"
1488 " AROS_LIBFUNC_EXIT\n"
1489 "}\n"
1490 "\n",
1491 cfg->basename
1496 static void
1497 writefunctable(FILE *out,
1498 struct config *cfg
1501 struct functionhead *funclistit = cfg->funclist;
1502 struct functionarg *arglistit;
1503 unsigned int lvo;
1504 int i;
1505 char *name, *type;
1506 int lastversion = 0;
1508 /* lvo contains the number of functions already printed in the functable */
1509 lvo = 0;
1511 if (!(cfg->options & OPTION_NORESIDENT))
1513 fprintf(out,
1514 "\n"
1515 "__section(\".text.romtag\") const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1516 "{\n"
1518 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
1520 fprintf(out,
1521 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(OpenLib),%s,1),\n"
1522 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(CloseLib),%s,2),\n"
1523 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExpungeLib),%s,3),\n"
1524 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExtFuncLib),%s,4),\n",
1525 cfg->basename, cfg->basename, cfg->basename, cfg->basename
1527 lvo += 4;
1529 if (cfg->modtype == MCC || cfg->modtype == MUI || cfg->modtype == MCP)
1531 lvo++;
1532 fprintf(out,
1533 " &AROS_SLIB_ENTRY(MCC_Query,%s,%d),\n",
1534 cfg->basename, lvo
1537 else if (cfg->modtype == DATATYPE)
1539 lvo++;
1540 fprintf(out,
1541 " &AROS_SLIB_ENTRY(ObtainEngine,%s,%d),\n",
1542 cfg->basename, lvo
1546 else /* NORESIDENT */
1548 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
1550 int neednull = 0;
1551 struct functionhead *funclistit2;
1553 if (funclistit->lvo != 1)
1555 fprintf(stderr, "Module without a generated resident structure has to provide the Open function (LVO==1)\n");
1556 exit(20);
1558 else
1559 funclistit = funclistit->next;
1561 if (funclistit->lvo != 2)
1563 fprintf(stderr, "Module without a generated resident structure has to provide the Close function (LVO==2)\n");
1564 exit(20);
1566 else
1567 funclistit = funclistit->next;
1569 if (funclistit->lvo == 3)
1570 funclistit = funclistit->next;
1571 else
1572 neednull = 1;
1574 if (funclistit->lvo == 4)
1575 funclistit = funclistit->next;
1576 else
1577 neednull = 1;
1579 if (neednull)
1580 fprintf(out,
1581 "\n"
1582 "AROS_UFH1S(int, %s_null,\n"
1583 " AROS_UFHA(struct Library *, libbase, A6)\n"
1584 ")\n"
1585 "{\n"
1586 " AROS_USERFUNC_INIT\n"
1587 " return 0;\n"
1588 " AROS_USERFUNC_EXIT\n"
1589 "}\n",
1590 cfg->modulename
1593 funclistit = cfg->funclist;
1594 funclistit2 = funclistit->next;
1595 fprintf(out,
1596 "\n"
1597 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1598 "{\n"
1599 " &AROS_SLIB_ENTRY(%s,%s,%d),\n"
1600 " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1601 funclistit->internalname, cfg->basename, lvo+1,
1602 funclistit2->internalname, cfg->basename, lvo+2
1604 lvo += 2;
1605 funclistit = funclistit2->next;
1607 if (funclistit->lvo == 3)
1609 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1610 funclistit->internalname, cfg->basename, lvo+1
1612 funclistit = funclistit->next;
1614 else
1615 fprintf(out, " &%s_null,\n", cfg->modulename);
1616 lvo++;
1618 if (funclistit->lvo == 4)
1620 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1621 funclistit->internalname, cfg->basename, lvo+1
1623 funclistit = funclistit->next;
1625 else
1626 fprintf(out, " &%s_null,\n", cfg->modulename);
1627 lvo++;
1629 else
1631 fprintf(out,
1632 "\n"
1633 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1634 "{\n");
1638 while (funclistit != NULL)
1640 for (i = lvo+1; i<funclistit->lvo; i++)
1641 fprintf(out, " NULL,\n");
1642 lvo = funclistit->lvo;
1644 switch (funclistit->libcall)
1646 case STACK:
1647 case REGISTER:
1648 case REGISTERMACRO:
1649 if (funclistit->version != lastversion) {
1650 lastversion = funclistit->version;
1651 fprintf(out, " /* Version %d */\n", lastversion);
1653 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n", funclistit->internalname, cfg->basename, lvo);
1654 break;
1656 default:
1657 fprintf(stderr, "Internal error: unhandled libcall type in writestart\n");
1658 exit(20);
1659 break;
1662 funclistit = funclistit->next;
1665 fprintf(out, " (void *)-1\n};\n");
1669 static void writesets(FILE *out, struct config *cfg)
1671 fprintf(out,
1672 "DEFINESET(INIT)\n"
1673 "DEFINESET(EXIT)\n"
1675 if (cfg->modtype != HANDLER)
1676 fprintf(out,
1677 "DEFINESET(CTORS)\n"
1678 "DEFINESET(DTORS)\n"
1679 "DEFINESET(INIT_ARRAY)\n"
1680 "DEFINESET(FINI_ARRAY)\n"
1681 "DEFINESET(INITLIB)\n"
1682 "DEFINESET(EXPUNGELIB)\n"
1684 if (!(cfg->options & OPTION_NOOPENCLOSE))
1685 fprintf(out,
1686 "DEFINESET(OPENLIB)\n"
1687 "DEFINESET(CLOSELIB)\n"
1689 if (cfg->modtype == DEVICE)
1690 fprintf(out,
1691 "DEFINESET(OPENDEV)\n"
1692 "DEFINESET(CLOSEDEV)\n"
1694 if (cfg->classlist != NULL)
1695 fprintf(out,
1696 "DEFINESET(CLASSESINIT)\n"
1697 "DEFINESET(CLASSESEXPUNGE)\n"
1699 fprintf(out, "\n");