grub2: bring back build of aros-side grub2 tools
[AROS.git] / tools / genmodule / writestart.c
blobec4ebeb569b715007a9e4acfbe512abab5cb0467
1 /*
2 Copyright © 1995-2016, 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(void)\n"
318 "{\n"
319 " return (char *)GetTaskStorageSlot(__GM_BaseSlot);\n"
320 "}\n"
321 "void __aros_setoffsettable(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();\n"
328 "}\n",
329 cfg->libbasetypeptrextern, cfg->libbase,
330 cfg->libbasetypeptrextern
332 } else if (cfg->rellibs || (cfg->options & OPTION_STACKCALL)) {
333 fprintf(out,
334 "#ifdef __aros_getoffsettable\n"
336 if ((cfg->options & OPTION_STACKCALL))
337 fprintf(out,
338 "#error Redefining __aros_setoffsettable is not permitted with stackcall APIs\n"
340 else
341 fprintf(out,
342 "#define __aros_getbase_%s() __aros_getoffsettable()\n",
343 cfg->libbase
345 fprintf(out,
346 "#else /* !__aros_getoffsettable */\n"
347 "static char *__GM_OffsetTable;\n"
348 "char *__aros_getoffsettable(void)\n"
349 "{\n"
350 " return __GM_OffsetTable;\n"
351 "}\n"
352 "BOOL __aros_setoffsettable(char *base)\n"
353 "{\n"
354 " __GM_OffsetTable = base;\n"
355 " return TRUE;\n"
356 "}\n"
357 "%s__aros_getbase_%s(void)\n"
358 "{\n"
359 " return (%s)__aros_getoffsettable();\n"
360 "}\n"
361 "#endif /* __aros_getoffsettable */\n"
362 "\n",
363 cfg->libbasetypeptrextern, cfg->libbase,
364 cfg->libbasetypeptrextern
368 if (cfg->rellibs)
370 struct stringlist *sl;
372 for (sl = cfg->rellibs; sl; sl = sl->next)
374 fprintf(out,
375 "AROS_IMPORT_ASM_SYM(void *,__GM_rellib_base_%s,AROS_RELLIB_BASE_%s);\n"
376 , sl->s
377 , upname(sl->s)
382 for (classlistit = cfg->classlist; classlistit != NULL; classlistit = classlistit->next)
384 /* For the main class basename is the same as the module basename */
385 if (strcmp(classlistit->basename, cfg->basename) == 0)
387 if (classlistit->classptr_var == NULL)
389 fprintf(out,
390 "#if !defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
391 "static APTR GM_UNIQUENAME(%sClass);\n"
392 "#define GM_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
393 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
394 "#define %s_STORE_CLASSPTR 1\n"
395 "#elif defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
396 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_CLASSPTR_FIELD(LIBBASE))\n"
397 "#elif !defined(GM_CLASSPTR_FIELD) && defined(%s_CLASSPTR_FIELD)\n"
398 "#define GM_CLASSPTR_FIELD(LIBBASE) (%s_CLASSPTR_FIELD(LIBBASE))\n"
399 "#endif\n",
400 classlistit->basename,
401 classlistit->basename,
402 classlistit->basename,
403 classlistit->basename, classlistit->basename,
404 classlistit->basename,
405 classlistit->basename,
406 classlistit->basename,
407 classlistit->basename,
408 classlistit->basename
411 else
413 fprintf(out,
414 "#define GM_CLASSPTR_FIELD(LIBBASE) (%s)\n"
415 "#define %s_CLASSPTR_FIELD(LIBBASE) (%s)\n"
416 "#define %s_STORE_CLASSPTR 1\n",
417 classlistit->classptr_var,
418 classlistit->basename, classlistit->classptr_var,
419 classlistit->basename
423 else
425 if (classlistit->classptr_var == NULL)
427 fprintf(out,
428 "#if !defined(%s_CLASSPTR_FIELD)\n"
429 "static APTR GM_UNIQUENAME(%sClass);\n"
430 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
431 "#define %s_STORE_CLASSPTR 1\n"
432 "#endif\n",
433 classlistit->basename,
434 classlistit->basename,
435 classlistit->basename, classlistit->basename,
436 classlistit->basename
439 else
441 fprintf(out,
442 "#define %s_CLASSPTR_FIELD(LIBBASE) (%s)\n"
443 "#define %s_STORE_CLASSPTR 1\n",
444 classlistit->basename, classlistit->classptr_var,
445 classlistit->basename
451 /* Write out the defines for the functions of the function table */
452 writefuncdefs(out, cfg, cfg->funclist);
453 /* Write internal stubs */
454 writefuncinternalstubs(out, cfg, cfg->funclist);
455 fprintf(out, "\n");
458 /* Write out the includes needed for the classes */
459 if (cfg->classlist != NULL)
460 writeboopsiincludes(out);
462 for (classlistit = cfg->classlist; classlistit != NULL; classlistit = classlistit->next)
464 switch (classlistit->classtype)
466 case MUI:
467 case MCC:
468 case MCP:
469 if (!muiinc)
471 writemuiincludes(out);
472 muiinc = 1;
474 /* Fall through: also write boopsi includes */
475 case GADGET:
476 case DATATYPE:
477 case CLASS:
478 case IMAGE:
479 if (!boopsiinc)
481 writeboopsiincludes(out);
482 boopsiinc = 1;
484 break;
485 case HIDD:
486 if (!oopinc)
488 writeoopincludes(out);
489 oopinc = 1;
491 break;
492 default:
493 fprintf(stderr, "Internal error: unhandled classtype in writedecl\n");
494 exit(20);
500 static void writedeclsets(FILE *out, struct config *cfg)
502 /* PROGRAM_ENTRIES is marked as handled but are just ignored in modules */
503 fprintf(out,
504 "THIS_PROGRAM_HANDLES_SYMBOLSET(INIT)\n"
505 "THIS_PROGRAM_HANDLES_SYMBOLSET(EXIT)\n"
506 "DECLARESET(INIT)\n"
507 "DECLARESET(EXIT)\n"
508 "THIS_PROGRAM_HANDLES_SYMBOLSET(PROGRAM_ENTRIES)\n"
509 "DECLARESET(PROGRAM_ENTRIES)\n"
511 if (cfg->modtype != HANDLER)
512 fprintf(out,
513 "THIS_PROGRAM_HANDLES_SYMBOLSET(CTORS)\n"
514 "THIS_PROGRAM_HANDLES_SYMBOLSET(DTORS)\n"
515 "DECLARESET(CTORS)\n"
516 "DECLARESET(DTORS)\n"
517 "THIS_PROGRAM_HANDLES_SYMBOLSET(INIT_ARRAY)\n"
518 "THIS_PROGRAM_HANDLES_SYMBOLSET(FINI_ARRAY)\n"
519 "DECLARESET(INIT_ARRAY)\n"
520 "DECLARESET(FINI_ARRAY)\n"
521 "THIS_PROGRAM_HANDLES_SYMBOLSET(INITLIB)\n"
522 "THIS_PROGRAM_HANDLES_SYMBOLSET(EXPUNGELIB)\n"
523 "DECLARESET(INITLIB)\n"
524 "DECLARESET(EXPUNGELIB)\n"
526 if (!(cfg->options & OPTION_NOAUTOLIB))
528 fprintf(out,
529 "THIS_PROGRAM_HANDLES_SYMBOLSET(LIBS)\n"
530 "DECLARESET(LIBS)\n"
532 if (cfg->rellibs)
533 fprintf(out,
534 "THIS_PROGRAM_HANDLES_SYMBOLSET(RELLIBS)\n"
535 "DECLARESET(RELLIBS)\n"
538 if (!(cfg->options & OPTION_NOOPENCLOSE))
539 fprintf(out,
540 "THIS_PROGRAM_HANDLES_SYMBOLSET(OPENLIB)\n"
541 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLOSELIB)\n"
542 "DECLARESET(OPENLIB)\n"
543 "DECLARESET(CLOSELIB)\n"
545 if (cfg->modtype == DEVICE)
546 fprintf(out,
547 "THIS_PROGRAM_HANDLES_SYMBOLSET(OPENDEV)\n"
548 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLOSEDEV)\n"
549 "DECLARESET(OPENDEV)\n"
550 "DECLARESET(CLOSEDEV)\n"
552 if (cfg->classlist != NULL)
553 fprintf(out,
554 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLASSESINIT)\n"
555 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLASSESEXPUNGE)\n"
556 "DECLARESET(CLASSESINIT)\n"
557 "DECLARESET(CLASSESEXPUNGE)\n"
558 "#define ADD2INITCLASSES(symbol, pri) ADD2SET(symbol, CLASSESINIT, pri)\n"
559 "#define ADD2EXPUNGECLASSES(symbol, pri) ADD2SET(symbol, CLASSESEXPUNGE, pri)\n"
561 fprintf(out, "\n");
565 static void writeresident(FILE *out, struct config *cfg)
567 char *rt_skip = cfg->addromtag;
569 if (rt_skip)
570 fprintf(out, "extern const struct Resident %s;\n", rt_skip);
571 else
573 rt_skip = "GM_UNIQUENAME(End)";
574 fprintf(out, "extern const int %s;\n", rt_skip);
576 fprintf(out,
577 "extern const APTR GM_UNIQUENAME(FuncTable)[];\n"
579 if (cfg->options & OPTION_RESAUTOINIT)
580 fprintf(out, "static const struct InitTable GM_UNIQUENAME(InitTable);\n");
581 fprintf(out,
582 "\n"
583 "extern const char GM_UNIQUENAME(LibName)[];\n"
584 "extern const char GM_UNIQUENAME(LibID)[];\n"
585 "extern const char GM_UNIQUENAME(Copyright)[];\n"
586 "\n"
589 if (cfg->options & OPTION_RESAUTOINIT)
591 fprintf(out,
592 "#define __freebase(LIBBASE)\\\n"
593 "do {\\\n"
594 " UWORD negsize, possize;\\\n"
595 " UBYTE *negptr = (UBYTE *)LIBBASE;\\\n"
596 " negsize = ((struct Library *)LIBBASE)->lib_NegSize;\\\n"
597 " negptr -= negsize;\\\n"
598 " possize = ((struct Library *)LIBBASE)->lib_PosSize;\\\n"
599 " FreeMem (negptr, negsize+possize);\\\n"
600 "} while(0)\n"
601 "\n");
604 fprintf(out,
605 "AROS_UFP3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
606 " AROS_UFPA(LIBBASETYPEPTR, LIBBASE, D0),\n"
607 " AROS_UFPA(BPTR, segList, A0),\n"
608 " AROS_UFPA(struct ExecBase *, sysBase, A6)\n"
609 ");\n"
611 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
613 fprintf(out,
614 "AROS_LD1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
615 " AROS_LDA(LIBBASETYPEPTR, extralh, D0),\n"
616 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
617 ");\n"
618 "\n",
619 cfg->basename
622 fprintf(out,
623 "__section(\".text.romtag\") struct Resident const GM_UNIQUENAME(ROMTag) =\n"
624 "{\n"
625 " RTC_MATCHWORD,\n"
626 " (struct Resident *)&GM_UNIQUENAME(ROMTag),\n"
627 " (APTR)&%s,\n"
628 " RESIDENTFLAGS,\n"
629 " VERSION_NUMBER,\n",
630 rt_skip
632 switch (cfg->modtype)
634 case LIBRARY:
635 case MUI:
636 case MCC:
637 case MCP:
638 case GADGET:
639 case DATATYPE:
640 case USBCLASS:
641 case HIDD:
642 fprintf(out, " NT_LIBRARY,\n");
643 break;
644 case DEVICE:
645 fprintf(out, " NT_DEVICE,\n");
646 break;
647 case RESOURCE:
648 case HANDLER:
649 fprintf(out, " NT_RESOURCE,\n");
650 break;
651 default:
652 fprintf(stderr, "Internal error: unsupported modtype for NT_...\n");
653 exit(20);
654 break;
656 fprintf(out,
657 " RESIDENTPRI,\n"
658 " (CONST_STRPTR)&GM_UNIQUENAME(LibName)[0],\n"
659 " (CONST_STRPTR)&GM_UNIQUENAME(LibID)[6],\n"
661 if (cfg->options & OPTION_RESAUTOINIT)
663 fprintf(out,
664 " (APTR)&GM_UNIQUENAME(InitTable)\n"
665 "};\n"
666 "\n"
667 "__section(\".text.romtag\") static struct InitTable\n"
668 "{\n"
669 " IPTR Size;\n"
670 " const APTR *FuncTable;\n"
671 " struct DataTable *DataTable;\n"
672 " APTR InitLibTable;\n"
673 "}\n"
674 "const GM_UNIQUENAME(InitTable) =\n"
675 "{\n"
676 " LIBBASESIZE,\n"
677 " &GM_UNIQUENAME(FuncTable)[0],\n"
678 " NULL,\n"
679 " (APTR)GM_UNIQUENAME(InitLib)\n"
680 "};\n"
683 else
684 fprintf(out, " (APTR)GM_UNIQUENAME(InitLib)\n};\n");
686 fprintf(out,
687 "\n"
688 "__section(\".text.romtag\") const char GM_UNIQUENAME(LibName)[] = MOD_NAME_STRING;\n"
689 "__section(\".text.romtag\") const char GM_UNIQUENAME(LibID)[] = VERSION_STRING;\n"
690 "__section(\".text.romtag\") const char GM_UNIQUENAME(Copyright)[] = COPYRIGHT_STRING;\n"
691 "\n"
695 static void writehandler(FILE *out, struct config *cfg)
697 int i, handlers=0;
698 struct handlerinfo *hl;
699 int need_fse = 0, need_dos = 0;
701 fprintf(out,
702 "\n"
703 "#include <resources/filesysres.h>\n"
704 "#include <aros/system.h>\n"
705 "#include <proto/arossupport.h>\n"
706 "#include <proto/expansion.h>\n"
707 "\n"
710 for (hl = cfg->handlerlist; hl != NULL; hl = hl->next) {
711 if (hl->type == HANDLER_DOSNODE)
712 need_dos = 1;
713 else
714 need_fse = 1;
715 handlers++;
718 fprintf(out,
719 "\n"
720 "LONG %s(struct ExecBase *sysBase);\n"
721 "extern const LONG __aros_libreq_SysBase __attribute__((weak));\n"
722 "\n"
723 "__startup AROS_PROCH(GM_UNIQUENAME(Handler), argptr, argsize, SysBase)\n"
724 "{\n"
725 " AROS_PROCFUNC_INIT\n"
726 "\n"
727 " LONG ret = RETURN_FAIL;\n"
728 "\n"
729 " if (!SysBase || SysBase->LibNode.lib_Version < __aros_libreq_SysBase)\n"
730 " return ERROR_INVALID_RESIDENT_LIBRARY;\n"
731 " if (set_call_funcs(SETNAME(INIT), 1, 1)) {\n"
732 " ret = %s(SysBase);\n"
733 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
734 " }\n"
735 "\n"
736 " return ret;\n"
737 "\n"
738 " AROS_PROCFUNC_EXIT\n"
739 "}\n"
740 , cfg->handlerfunc
741 , cfg->handlerfunc
744 fprintf(out,
745 "\n"
746 "static inline BOOL GM_UNIQUENAME(InitHandler)(struct ExecBase *SysBase)\n"
747 "{\n"
750 if (!need_dos && !need_fse) {
751 fprintf(out,
752 " return TRUE;\n"
753 "}\n"
755 return;
758 fprintf(out,
759 " BPTR seg;\n"
762 if (need_dos) {
763 fprintf(out,
764 " struct Library *ExpansionBase;\n"
767 if (need_fse) {
768 fprintf(out,
769 " struct FileSysResource *fsr;\n"
770 " struct FileSysEntry *fse;\n"
773 if (need_fse) {
774 fprintf(out,
775 " fsr = (struct FileSysResource *)OpenResource(\"FileSystem.resource\");\n"
776 " if (fsr == NULL)\n"
777 " return FALSE;\n"
780 if (need_dos) {
781 fprintf(out,
782 " ExpansionBase = OpenLibrary(\"expansion.library\", 36);\n"
783 " if (ExpansionBase == NULL)\n"
784 " return FALSE;\n"
787 fprintf(out,
788 " seg = CreateSegList(GM_UNIQUENAME(Handler));\n"
789 " if (seg != BNULL) {\n"
791 for (hl = cfg->handlerlist; hl != NULL; hl = hl->next)
793 switch (hl->type)
795 case HANDLER_DOSNODE:
796 fprintf(out,
797 "\n"
798 " {\n"
799 " struct DeviceNode *node;\n"
800 " IPTR pp[] = { \n"
801 " (IPTR)\"%s\",\n"
802 " (IPTR)NULL,\n"
803 " (IPTR)0,\n"
804 " (IPTR)0,\n"
805 " (IPTR)0\n"
806 " };\n"
807 " node = MakeDosNode((APTR)pp);\n"
808 " if (node) {\n"
809 " node->dn_StackSize = %u;\n"
810 " node->dn_SegList = seg;\n"
811 " node->dn_Startup = (BPTR)%d;\n"
812 " node->dn_Priority = %d;\n"
813 " node->dn_GlobalVec = (BPTR)(SIPTR)-1;\n"
814 " AddBootNode(%d, 0, node, NULL);\n"
815 " }\n"
816 " }\n"
817 "\n"
818 , hl->name
819 , hl->stacksize
820 , hl->startup
821 , hl->priority
822 , hl->bootpri
824 break;
825 case HANDLER_RESIDENT:
826 case HANDLER_DOSTYPE:
827 fprintf(out,
828 "\n"
829 " /* Check to see if we can allocate the memory for the fse */\n"
830 " fse = AllocMem(sizeof(*fse), MEMF_CLEAR);\n"
831 " if (fse) {\n"
832 " fse->fse_Node.ln_Name = VERSION_STRING;\n"
833 " fse->fse_Node.ln_Pri = %d;\n"
834 " fse->fse_DosType = 0x%08x;\n"
835 " fse->fse_Version = (MAJOR_VERSION << 16) | MINOR_VERSION;\n"
836 " fse->fse_PatchFlags = FSEF_SEGLIST | FSEF_GLOBALVEC | FSEF_PRIORITY;\n"
837 , hl->autodetect
838 , hl->id
840 if (hl->stacksize)
842 fprintf(out,
843 " fse->fse_PatchFlags |= FSEF_STACKSIZE;\n"
844 " fse->fse_StackSize = %d;\n"
845 , hl->stacksize
848 if (hl->name)
849 fprintf(out,
850 " fse->fse_PatchFlags |= FSEF_HANDLER;\n"
851 " fse->fse_Handler = AROS_CONST_BSTR(\"%s\");\n"
852 , hl->name);
853 fprintf(out,
854 " fse->fse_Priority = %d;\n"
855 " fse->fse_SegList = seg;\n"
856 " fse->fse_GlobalVec = (BPTR)(SIPTR)-1;\n"
857 " fse->fse_Startup = (BPTR)%d;\n"
858 "\n"
859 " /* Add to the list. I know forbid and permit are\n"
860 " * a little unnecessary for the pre-multitasking state\n"
861 " * we should be in at this point, but you never know\n"
862 " * who's going to blindly copy this code as an example.\n"
863 " */\n"
864 " Forbid();\n"
865 " Enqueue(&fsr->fsr_FileSysEntries, (struct Node *)fse);\n"
866 " Permit();\n"
867 " }\n"
868 , hl->priority
869 , hl->startup
871 break;
874 fprintf(out,
875 " }\n"
877 if (need_dos) {
878 fprintf(out,
879 " CloseLibrary(ExpansionBase);\n"
882 fprintf(out,
883 " return TRUE;\n"
884 "}\n"
885 "\n"
889 static void writeinitlib(FILE *out, struct config *cfg)
891 if (cfg->handlerlist)
892 writehandler(out, cfg);
894 fprintf(out,
895 "extern const LONG __aros_libreq_SysBase __attribute__((weak));\n"
896 "\n"
897 "AROS_UFH3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
898 " AROS_UFHA(LIBBASETYPEPTR, LIBBASE, D0),\n"
899 " AROS_UFHA(BPTR, segList, A0),\n"
900 " AROS_UFHA(struct ExecBase *, sysBase, A6)\n"
901 ")\n"
902 "{\n"
903 " AROS_USERFUNC_INIT\n"
906 if (cfg->modtype == HANDLER) {
907 fprintf(out,
908 "\n"
909 " GM_UNIQUENAME(InitHandler)(sysBase);\n"
910 " return LIBBASE;\n"
911 "\n"
912 " AROS_USERFUNC_EXIT\n"
913 "}\n"
914 "\n"
916 return;
919 fprintf(out,
920 "\n"
921 " int ok;\n"
922 " int initcalled = 0;\n"
924 /* Set the global SysBase, needed for __aros_setoffsettable()/__aros_getoffsettable() */
925 if (cfg->options & OPTION_DUPBASE)
926 fprintf(out,
927 " SysBase = sysBase;\n"
929 else
930 fprintf(out,
931 " struct ExecBase *SysBase = sysBase;\n"
933 fprintf(out,
934 "\n"
935 "#ifdef GM_SYSBASE_FIELD\n"
936 " GM_SYSBASE_FIELD(LIBBASE) = (APTR)SysBase;\n"
937 "#endif\n"
938 " if (!SysBase || SysBase->LibNode.lib_Version < __aros_libreq_SysBase)\n"
939 " return NULL;\n"
940 "\n"
943 if (cfg->options & OPTION_RESAUTOINIT) {
944 fprintf(out,
945 "#ifdef GM_OOPBASE_FIELD\n"
946 " GM_OOPBASE_FIELD(LIBBASE) = OpenLibrary(\"oop.library\",0);\n"
947 " if (GM_OOPBASE_FIELD(LIBBASE) == NULL)\n"
948 " return NULL;\n"
949 "#endif\n"
953 if (!(cfg->options & OPTION_RESAUTOINIT))
955 fprintf(out,
956 " int vecsize;\n"
957 " struct Node *n;\n"
958 " char *mem;\n"
959 "\n"
960 " vecsize = FUNCTIONS_COUNT * LIB_VECTSIZE;\n"
961 " if (vecsize > 0)\n"
962 " vecsize = ((vecsize-1)/sizeof(IPTR) + 1)*sizeof(IPTR);\n"
963 " mem = AllocMem(vecsize+sizeof(LIBBASETYPE), MEMF_PUBLIC|MEMF_CLEAR);\n"
964 " if (mem == NULL)\n"
965 " return NULL;\n"
966 " LIBBASE = (LIBBASETYPEPTR)(mem + vecsize);\n"
967 " n = (struct Node *)LIBBASE;\n"
968 " n->ln_Type = NT_RESOURCE;\n"
969 " n->ln_Pri = RESIDENTPRI;\n"
970 " n->ln_Name = (char *)GM_UNIQUENAME(LibName);\n"
971 " MakeFunctions(LIBBASE, (APTR)GM_UNIQUENAME(FuncTable), NULL);\n"
973 if ((cfg->modtype != RESOURCE) && (cfg->options & OPTION_SELFINIT))
975 fprintf(out,
976 " ((struct Library*)LIBBASE)->lib_NegSize = vecsize;\n"
977 " ((struct Library*)LIBBASE)->lib_PosSize = sizeof(LIBBASETYPE);\n"
982 else
984 fprintf(out,
985 " ((struct Library *)LIBBASE)->lib_Revision = REVISION_NUMBER;\n"
989 if (cfg->options & OPTION_DUPBASE)
990 fprintf(out,
991 " __GM_BaseSlot = AllocTaskStorageSlot();\n"
992 " if (!SetTaskStorageSlot(__GM_BaseSlot, (IPTR)LIBBASE)) {\n"
993 " FreeTaskStorageSlot(__GM_BaseSlot);\n"
994 " return NULL;\n"
995 " }\n"
997 else if (cfg->rellibs || (cfg->options & OPTION_STACKCALL))
998 fprintf(out,
999 " __aros_setoffsettable((char *)LIBBASE);\n"
1001 if (cfg->options & OPTION_PERTASKBASE)
1002 fprintf(out,
1003 " __pertaskslot = AllocTaskStorageSlot();\n"
1006 if (!(cfg->options & OPTION_NOEXPUNGE) && cfg->modtype!=RESOURCE)
1007 fprintf(out, " GM_SEGLIST_FIELD(LIBBASE) = segList;\n");
1008 if (cfg->options & OPTION_DUPBASE)
1009 fprintf(out, " GM_ROOTBASE_FIELD(LIBBASE) = (LIBBASETYPEPTR)LIBBASE;\n");
1010 fprintf(out, " if (");
1011 if (!(cfg->options & OPTION_NOAUTOLIB))
1012 fprintf(out, "set_open_libraries() && ");
1013 if (cfg->rellibs)
1014 fprintf(out, "set_open_rellibraries(LIBBASE) && ");
1015 fprintf(out,
1016 "set_call_funcs(SETNAME(INIT), 1, 1) &&"
1018 if (cfg->classlist != NULL)
1019 fprintf(out, "set_call_libfuncs(SETNAME(CLASSESINIT), 1, 1, LIBBASE) && ");
1020 fprintf(out,
1021 "1)\n"
1022 " {\n"
1023 " set_call_funcs(SETNAME(CTORS), -1, 0);\n"
1024 " set_call_funcs(SETNAME(INIT_ARRAY), 1, 0);\n"
1025 "\n"
1028 fprintf(out,
1029 " initcalled = 1;\n"
1030 " ok = set_call_libfuncs(SETNAME(INITLIB), 1, 1, LIBBASE);\n"
1031 " }\n"
1032 " else\n"
1033 " ok = 0;\n"
1034 "\n"
1035 " if (!ok)\n"
1036 " {\n"
1037 " if (initcalled)\n"
1038 " set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 0, LIBBASE);\n"
1039 " set_call_funcs(SETNAME(FINI_ARRAY), -1, 0);\n"
1040 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
1041 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
1043 if (cfg->classlist != NULL)
1044 fprintf(out, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, LIBBASE);\n");
1045 if (cfg->rellibs)
1046 fprintf(out, " set_close_rellibraries(LIBBASE);\n");
1047 if (!(cfg->options & OPTION_NOAUTOLIB))
1048 fprintf(out, " set_close_libraries();\n");
1050 if (cfg->options & OPTION_RESAUTOINIT)
1052 fprintf(out,
1053 "\n"
1054 " __freebase(LIBBASE);\n"
1057 else
1059 fprintf(out,
1060 "\n"
1061 " FreeMem(mem, vecsize+LIBBASESIZE);\n"
1064 fprintf(out,
1065 " return NULL;\n"
1066 " }\n"
1067 " else\n"
1068 " {\n"
1071 if (!(cfg->options & OPTION_RESAUTOINIT) && !(cfg->options & OPTION_SELFINIT))
1073 switch (cfg->modtype)
1075 case RESOURCE:
1076 fprintf(out, " AddResource(LIBBASE);\n");
1077 break;
1079 case DEVICE:
1080 fprintf(out, " AddDevice(LIBBASE);\n");
1082 default:
1083 /* Everything else is library */
1084 fprintf(out, " AddLibrary(LIBBASE);\n");
1085 break;
1089 fprintf(out,
1090 " return LIBBASE;\n"
1091 " }\n"
1092 "\n"
1093 " AROS_USERFUNC_EXIT\n"
1094 "}\n"
1095 "\n"
1099 static void writeopenlib(FILE *out, struct config *cfg)
1101 switch (cfg->modtype)
1103 case RESOURCE:
1104 fprintf(stderr, "Internal error: writeopenlib called for a resource\n");
1105 break;
1106 case HANDLER:
1107 fprintf(stderr, "Internal error: writeopenlib called for a handler\n");
1108 break;
1109 case DEVICE:
1110 if (cfg->options & OPTION_NOOPENCLOSE)
1111 fprintf(out,
1112 "AROS_LD3 (void, GM_UNIQUENAME(OpenLib),\n"
1113 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1114 " AROS_LDA(ULONG, unitnum, D0),\n"
1115 " AROS_LDA(ULONG, flags, D1),\n"
1116 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1117 ");\n",
1118 cfg->basename
1120 else
1122 fprintf(out,
1123 "AROS_LH3 (void, GM_UNIQUENAME(OpenLib),\n"
1124 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1125 " AROS_LHA(IPTR, unitnum, D0),\n"
1126 " AROS_LHA(ULONG, flags, D1),\n"
1127 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1128 ")\n",
1129 cfg->basename
1131 fprintf(out,
1132 "{\n"
1133 " AROS_LIBFUNC_INIT\n"
1134 "\n"
1135 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, LIBBASE)\n"
1136 " && set_call_devfuncs(SETNAME(OPENDEV), 1, 1, LIBBASE, ioreq, unitnum, flags)\n"
1137 " )\n"
1138 " {\n"
1139 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1140 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1141 "\n"
1142 " ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;\n"
1143 " }\n"
1144 " else\n"
1145 " {\n"
1146 " if (ioreq->io_Error >= 0)\n"
1147 " ioreq->io_Error = IOERR_OPENFAIL;\n"
1148 " }\n"
1149 "\n"
1150 " return;\n"
1151 "\n"
1152 " AROS_LIBFUNC_EXIT\n"
1153 "}\n"
1154 "\n"
1157 break;
1158 default:
1159 if (cfg->options & OPTION_NOOPENCLOSE)
1161 fprintf(out,
1162 "AROS_LD1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
1163 " AROS_LDA (ULONG, version, D0),\n"
1164 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1165 ");\n",
1166 cfg->basename
1168 return;
1170 fprintf(out,
1171 "AROS_LH1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
1172 " AROS_LHA (ULONG, version, D0),\n"
1173 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1174 ")\n"
1175 "{\n"
1176 " AROS_LIBFUNC_INIT\n"
1177 "\n",
1178 cfg->basename
1180 if (!(cfg->options & OPTION_DUPBASE))
1182 fprintf(out,
1183 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, LIBBASE) )\n"
1184 " {\n"
1185 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1186 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1187 " return LIBBASE;\n"
1188 " }\n"
1189 "\n"
1190 " return NULL;\n"
1191 "\n"
1192 " AROS_LIBFUNC_EXIT\n"
1193 "}\n"
1194 "\n"
1197 else /* OPTION_DUPBASE */
1199 fprintf(out,
1200 " struct Library *newlib = NULL;\n"
1201 " UWORD possize = ((struct Library *)LIBBASE)->lib_PosSize;\n"
1202 " LIBBASETYPEPTR oldbase = (LIBBASETYPEPTR)__aros_getbase_%s();\n",
1203 cfg->libbase
1205 if (cfg->options & OPTION_PERTASKBASE)
1206 fprintf(out,
1207 " struct Task *thistask = FindTask(NULL);\n"
1208 " LIBBASETYPEPTR oldpertaskbase = __GM_GetPerTaskBase();\n"
1209 " if (!oldpertaskbase)\n"
1210 " oldpertaskbase = __GM_GetParentPerTaskBase();\n"
1211 " newlib = (struct Library *)oldpertaskbase;\n"
1212 " if (newlib)\n"
1213 " {\n"
1214 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1215 " if (dupbase->task != thistask)\n"
1216 " newlib = NULL;\n"
1217 " else if (thistask->tc_Node.ln_Type == NT_PROCESS\n"
1218 " && dupbase->retaddr != ((struct Process *)thistask)->pr_ReturnAddr\n"
1219 " )\n"
1220 " newlib = NULL;\n"
1221 " else\n"
1222 " dupbase->taskopencount++;\n"
1223 " }\n"
1226 fprintf(out,
1227 "\n"
1228 " if (newlib == NULL)\n"
1229 " {\n"
1230 " newlib = MakeLibrary(GM_UNIQUENAME(InitTable).FuncTable,\n"
1231 " GM_UNIQUENAME(InitTable).DataTable,\n"
1232 " NULL,\n"
1233 " GM_UNIQUENAME(InitTable).Size,\n"
1234 " (BPTR)NULL\n"
1235 " );\n"
1236 " if (newlib == NULL)\n"
1237 " return NULL;\n"
1238 "\n"
1239 " CopyMem(LIBBASE, newlib, possize);\n"
1240 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1241 " dupbase->oldbase = oldbase;\n"
1242 " __aros_setoffsettable((char *)newlib);\n"
1244 if (cfg->options & OPTION_PERTASKBASE)
1245 fprintf(out,
1246 " dupbase->task = thistask;\n"
1247 " if (thistask->tc_Node.ln_Type == NT_PROCESS)\n"
1248 " dupbase->retaddr = ((struct Process *)thistask)->pr_ReturnAddr;\n"
1249 " dupbase->oldpertaskbase = oldpertaskbase;\n"
1250 " dupbase->taskopencount = 1;\n"
1251 " __GM_SetPerTaskBase((LIBBASETYPEPTR)newlib);\n"
1253 fprintf(out,
1254 "\n"
1255 " if (!(set_open_rellibraries(newlib)\n"
1256 " && set_call_libfuncs(SETNAME(OPENLIB), 1, 1, newlib)\n"
1257 " )\n"
1258 " )\n"
1259 " {\n");
1260 if (cfg->options & OPTION_PERTASKBASE)
1261 fprintf(out,
1262 " __GM_SetPerTaskBase(oldpertaskbase);\n");
1263 fprintf(out,
1264 " __freebase(newlib);\n"
1265 " return NULL;\n"
1266 " }\n"
1267 "\n"
1268 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1269 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1270 " }\n"
1271 "\n"
1272 " return (LIBBASETYPEPTR)newlib;\n"
1273 "\n"
1274 " AROS_LIBFUNC_EXIT\n"
1275 "}\n"
1276 "\n"
1283 static void writecloselib(FILE *out, struct config *cfg)
1285 if (cfg->options & OPTION_NOOPENCLOSE)
1287 if (cfg->modtype != DEVICE)
1288 fprintf(out,
1289 "AROS_LD0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1290 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1291 ");\n",
1292 cfg->basename
1294 else
1295 fprintf(out,
1296 "AROS_LD1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1297 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1298 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1299 ");\n",
1300 cfg->basename
1302 return;
1304 if (cfg->modtype != DEVICE)
1305 fprintf(out,
1306 "AROS_LH0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1307 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1308 ")\n",
1309 cfg->basename
1311 else
1312 fprintf(out,
1313 "AROS_LH1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1314 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1315 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1316 ")\n",
1317 cfg->basename
1320 fprintf(out,
1321 "{\n"
1322 " AROS_LIBFUNC_INIT\n"
1323 "\n"
1325 if (cfg->modtype == DEVICE)
1326 fprintf(out,
1327 " if (!set_call_devfuncs(SETNAME(CLOSEDEV), -1, 1, LIBBASE, ioreq, 0, 0))\n"
1328 " {\n"
1329 " return BNULL;\n"
1330 " }\n"
1332 if (!(cfg->options & OPTION_DUPBASE))
1334 fprintf(out,
1335 " ((struct Library *)LIBBASE)->lib_OpenCnt--;\n"
1336 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, LIBBASE);\n"
1339 else /* OPTION_DUPBASE */
1341 fprintf(out,
1342 " LIBBASETYPEPTR rootbase = GM_ROOTBASE_FIELD(LIBBASE);\n"
1343 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)LIBBASE;\n"
1344 " __aros_setoffsettable(LIBBASE);\n"
1346 if (cfg->options & OPTION_PERTASKBASE)
1347 fprintf(out,
1348 " dupbase->taskopencount--;\n"
1349 " if (dupbase->taskopencount != 0)\n"
1350 " return BNULL;\n"
1352 fprintf(out,
1353 "\n"
1354 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, LIBBASE);\n"
1355 " set_close_rellibraries(LIBBASE);\n"
1356 " __aros_setoffsettable((char *)dupbase->oldbase);\n"
1358 if (cfg->options & OPTION_PERTASKBASE)
1359 fprintf(out,
1360 " __GM_SetPerTaskBase(((struct __GM_DupBase *)LIBBASE)->oldpertaskbase);\n"
1362 fprintf(out,
1363 " __freebase(LIBBASE);\n"
1364 " LIBBASE = rootbase;\n"
1365 " ((struct Library *)LIBBASE)->lib_OpenCnt--;\n"
1366 "\n"
1369 if (!(cfg->options & OPTION_NOEXPUNGE))
1370 fprintf(out,
1371 " if\n"
1372 " (\n"
1373 " (((struct Library *)LIBBASE)->lib_OpenCnt == 0)\n"
1374 " && (((struct Library *)LIBBASE)->lib_Flags & LIBF_DELEXP)\n"
1375 " )\n"
1376 " {\n"
1377 " return AROS_LC1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1378 " AROS_LCA(LIBBASETYPEPTR, LIBBASE, D0),\n"
1379 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
1380 " );\n"
1381 " }\n",
1382 cfg->basename
1384 fprintf(out,
1385 "\n"
1386 " return BNULL;\n"
1387 "\n"
1388 " AROS_LIBFUNC_EXIT\n"
1389 "}\n"
1390 "\n"
1395 static void writeexpungelib(FILE *out, struct config *cfg)
1397 fprintf(out,
1398 "AROS_LH1 (BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1399 " AROS_LHA(LIBBASETYPEPTR, extralh, D0),\n"
1400 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
1401 ")\n",
1402 cfg->basename
1404 fprintf(out,
1405 "{\n"
1406 " AROS_LIBFUNC_INIT\n"
1407 "\n"
1409 if (!(cfg->options & OPTION_NOEXPUNGE))
1411 if (cfg->options & OPTION_RESAUTOINIT) {
1412 fprintf(out,
1413 "#ifdef GM_SYSBASE_FIELD\n"
1414 " struct ExecBase *SysBase = (struct ExecBase *)GM_SYSBASE_FIELD(LIBBASE);\n"
1415 "#endif\n"
1418 if (cfg->options & OPTION_DUPBASE)
1419 fprintf(out, " __aros_setoffsettable(LIBBASE);\n");
1420 fprintf(out,
1421 "\n"
1422 " if ( ((struct Library *)LIBBASE)->lib_OpenCnt == 0 )\n"
1423 " {\n"
1424 " BPTR seglist = GM_SEGLIST_FIELD(LIBBASE);\n"
1425 "\n"
1426 " if(!set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 1, LIBBASE))\n"
1427 " {\n"
1428 " ((struct Library *)LIBBASE)->lib_Flags |= LIBF_DELEXP;\n"
1429 " return BNULL;\n"
1430 " }\n"
1431 "\n"
1432 " Remove((struct Node *)LIBBASE);\n"
1433 "\n"
1434 " set_call_funcs(SETNAME(FINI_ARRAY), -1, 0);\n"
1435 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
1436 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
1438 if (cfg->classlist != NULL)
1439 fprintf(out, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, LIBBASE);\n");
1440 if (cfg->rellibs)
1441 fprintf(out, " set_close_rellibraries(LIBBASE);\n");
1442 if (!(cfg->options & OPTION_NOAUTOLIB))
1443 fprintf(out, " set_close_libraries();\n"
1444 "#ifdef GM_OOPBASE_FIELD\n"
1445 " CloseLibrary((struct Library *)GM_OOPBASE_FIELD(LIBBASE));\n"
1446 "#endif\n"
1448 if (cfg->options & OPTION_PERTASKBASE)
1449 fprintf(out,
1450 " FreeTaskStorageSlot(__pertaskslot);\n"
1451 " __pertaskslot = 0;\n"
1453 fprintf(out,
1454 "\n"
1455 " __freebase(LIBBASE);\n"
1456 "\n"
1457 " return seglist;\n"
1458 " }\n"
1459 "\n"
1460 " ((struct Library *)LIBBASE)->lib_Flags |= LIBF_DELEXP;\n"
1463 fprintf(out,
1464 "\n"
1465 " return BNULL;\n"
1466 "\n"
1467 " AROS_LIBFUNC_EXIT\n"
1468 "}\n"
1469 "\n"
1474 static void writeextfunclib(FILE *out, struct config *cfg)
1476 fprintf(out,
1477 "AROS_LH0 (LIBBASETYPEPTR, GM_UNIQUENAME(ExtFuncLib),\n"
1478 " LIBBASETYPEPTR, LIBBASE, 4, %s\n"
1479 ")\n"
1480 "{\n"
1481 " AROS_LIBFUNC_INIT\n"
1482 " return NULL;\n"
1483 " AROS_LIBFUNC_EXIT\n"
1484 "}\n"
1485 "\n",
1486 cfg->basename
1491 static void
1492 writefunctable(FILE *out,
1493 struct config *cfg
1496 struct functionhead *funclistit = cfg->funclist;
1497 struct functionarg *arglistit;
1498 unsigned int lvo;
1499 int i;
1500 char *name, *type;
1501 int lastversion = 0;
1503 /* lvo contains the number of functions already printed in the functable */
1504 lvo = 0;
1506 if (!(cfg->options & OPTION_NORESIDENT))
1508 fprintf(out,
1509 "\n"
1510 "__section(\".text.romtag\") const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1511 "{\n"
1513 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
1515 fprintf(out,
1516 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(OpenLib),%s,1),\n"
1517 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(CloseLib),%s,2),\n"
1518 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExpungeLib),%s,3),\n"
1519 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExtFuncLib),%s,4),\n",
1520 cfg->basename, cfg->basename, cfg->basename, cfg->basename
1522 lvo += 4;
1524 if (cfg->modtype == MCC || cfg->modtype == MUI || cfg->modtype == MCP)
1526 lvo++;
1527 fprintf(out,
1528 " &AROS_SLIB_ENTRY(MCC_Query,%s,%d),\n",
1529 cfg->basename, lvo
1532 else if (cfg->modtype == DATATYPE)
1534 lvo++;
1535 fprintf(out,
1536 " &AROS_SLIB_ENTRY(ObtainEngine,%s,%d),\n",
1537 cfg->basename, lvo
1541 else /* NORESIDENT */
1543 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
1545 int neednull = 0;
1546 struct functionhead *funclistit2;
1548 if (funclistit->lvo != 1)
1550 fprintf(stderr, "Module without a generated resident structure has to provide the Open function (LVO==1)\n");
1551 exit(20);
1553 else
1554 funclistit = funclistit->next;
1556 if (funclistit->lvo != 2)
1558 fprintf(stderr, "Module without a generated resident structure has to provide the Close function (LVO==2)\n");
1559 exit(20);
1561 else
1562 funclistit = funclistit->next;
1564 if (funclistit->lvo == 3)
1565 funclistit = funclistit->next;
1566 else
1567 neednull = 1;
1569 if (funclistit->lvo == 4)
1570 funclistit = funclistit->next;
1571 else
1572 neednull = 1;
1574 if (neednull)
1575 fprintf(out,
1576 "\n"
1577 "AROS_UFH1S(int, %s_null,\n"
1578 " AROS_UFHA(struct Library *, libbase, A6)\n"
1579 ")\n"
1580 "{\n"
1581 " AROS_USERFUNC_INIT\n"
1582 " return 0;\n"
1583 " AROS_USERFUNC_EXIT\n"
1584 "}\n",
1585 cfg->modulename
1588 funclistit = cfg->funclist;
1589 funclistit2 = funclistit->next;
1590 fprintf(out,
1591 "\n"
1592 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1593 "{\n"
1594 " &AROS_SLIB_ENTRY(%s,%s,%d),\n"
1595 " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1596 funclistit->internalname, cfg->basename, lvo+1,
1597 funclistit2->internalname, cfg->basename, lvo+2
1599 lvo += 2;
1600 funclistit = funclistit2->next;
1602 if (funclistit->lvo == 3)
1604 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1605 funclistit->internalname, cfg->basename, lvo+1
1607 funclistit = funclistit->next;
1609 else
1610 fprintf(out, " &%s_null,\n", cfg->modulename);
1611 lvo++;
1613 if (funclistit->lvo == 4)
1615 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1616 funclistit->internalname, cfg->basename, lvo+1
1618 funclistit = funclistit->next;
1620 else
1621 fprintf(out, " &%s_null,\n", cfg->modulename);
1622 lvo++;
1624 else
1626 fprintf(out,
1627 "\n"
1628 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1629 "{\n");
1633 while (funclistit != NULL)
1635 for (i = lvo+1; i<funclistit->lvo; i++)
1636 fprintf(out, " NULL,\n");
1637 lvo = funclistit->lvo;
1639 switch (funclistit->libcall)
1641 case STACK:
1642 case REGISTER:
1643 case REGISTERMACRO:
1644 if (funclistit->version != lastversion) {
1645 lastversion = funclistit->version;
1646 fprintf(out, " /* Version %d */\n", lastversion);
1648 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n", funclistit->internalname, cfg->basename, lvo);
1649 break;
1651 default:
1652 fprintf(stderr, "Internal error: unhandled libcall type in writestart\n");
1653 exit(20);
1654 break;
1657 funclistit = funclistit->next;
1660 fprintf(out, " (void *)-1\n};\n");
1664 static void writesets(FILE *out, struct config *cfg)
1666 fprintf(out,
1667 "DEFINESET(INIT)\n"
1668 "DEFINESET(EXIT)\n"
1670 if (cfg->modtype != HANDLER)
1671 fprintf(out,
1672 "DEFINESET(CTORS)\n"
1673 "DEFINESET(DTORS)\n"
1674 "DEFINESET(INIT_ARRAY)\n"
1675 "DEFINESET(FINI_ARRAY)\n"
1676 "DEFINESET(INITLIB)\n"
1677 "DEFINESET(EXPUNGELIB)\n"
1679 if (!(cfg->options & OPTION_NOOPENCLOSE))
1680 fprintf(out,
1681 "DEFINESET(OPENLIB)\n"
1682 "DEFINESET(CLOSELIB)\n"
1684 if (cfg->modtype == DEVICE)
1685 fprintf(out,
1686 "DEFINESET(OPENDEV)\n"
1687 "DEFINESET(CLOSEDEV)\n"
1689 if (cfg->classlist != NULL)
1690 fprintf(out,
1691 "DEFINESET(CLASSESINIT)\n"
1692 "DEFINESET(CLASSESEXPUNGE)\n"
1694 fprintf(out, "\n");