make sure values passed to cmake are stripped.
[AROS.git] / tools / genmodule / writestart.c
blob259d7bce446d5b2420b2b06cf3f64b2745e5a8be
1 /*
2 Copyright © 1995-2019, 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"
194 if (!cfg->flavour)
196 fprintf(out,
197 "#include \"%s_libdefs.h\"\n"
198 "\n"
199 , cfg->modulename
202 else
204 fprintf(out,
205 "#include \"%s_%s_libdefs.h\"\n"
206 "\n"
207 , cfg->modulename, cfg->flavour
211 for (s = cfg->rellibs; s; s = s->next)
212 fprintf(out,
213 "#include <proto/%s.h>\n"
214 , s->s
216 fprintf(out,
217 "\n"
218 "#undef SysBase\n"
219 "#undef OOPBase\n"
220 "#undef UtilityBase\n"
221 "\n"
222 "#include <proto/exec.h>\n"
223 "#include <proto/alib.h>\n"
224 "\n"
227 /* Write out declaration section provided in the config file */
228 for (linelistit = cfg->cdeflines; linelistit != NULL; linelistit = linelistit->next)
230 fprintf(out, "%s\n", linelistit->s);
233 /* Is there a variable for storing the segList ? */
234 if (!(cfg->options & OPTION_NOEXPUNGE) && cfg->modtype!=RESOURCE && cfg->modtype != HANDLER)
236 fprintf(out,
237 "#ifndef GM_SEGLIST_FIELD\n"
238 "static BPTR __attribute__((unused)) GM_UNIQUENAME(seglist);\n"
239 "#define GM_SEGLIST_FIELD(LIBBASE) (GM_UNIQUENAME(seglist))\n"
240 "#endif\n"
243 if (cfg->options & OPTION_DUPBASE)
244 fprintf(out,
245 "/* Required for TaskStorage manipulation */\n"
246 "extern struct ExecBase *SysBase;\n"
248 if (cfg->options & OPTION_DUPBASE)
250 fprintf(out,
251 "#ifndef GM_ROOTBASE_FIELD\n"
252 "static LIBBASETYPEPTR GM_UNIQUENAME(rootbase);\n"
253 "#define GM_ROOTBASE_FIELD(LIBBASE) (GM_UNIQUENAME(rootbase))\n"
254 "#endif\n"
255 "struct __GM_DupBase {\n"
256 " LIBBASETYPE base;\n"
257 " LIBBASETYPEPTR oldbase;\n"
259 if (cfg->options & OPTION_PERTASKBASE)
261 fprintf(out,
262 " ULONG taskopencount;\n"
263 " struct Task *task;\n"
264 " APTR retaddr;\n"
265 " LIBBASETYPEPTR oldpertaskbase;\n"
268 fprintf(out,
269 "};\n"
271 if (cfg->options & OPTION_PERTASKBASE)
273 fprintf(out,
274 "static LONG __pertaskslot;\n"
275 "LIBBASETYPEPTR __GM_GetBaseParent(LIBBASETYPEPTR base)\n"
276 "{\n"
277 " return ((struct __GM_DupBase *)base)->oldpertaskbase;\n"
278 "}\n"
279 "static inline LIBBASETYPEPTR __GM_GetPerTaskBase(void)\n"
280 "{\n"
281 " return (LIBBASETYPEPTR)GetTaskStorageSlot(__pertaskslot);\n"
282 "}\n"
283 "static inline LIBBASETYPEPTR __GM_GetParentPerTaskBase(void)\n"
284 "{\n"
285 " return (LIBBASETYPEPTR)GetParentTaskStorageSlot(__pertaskslot);\n"
286 "}\n"
287 "static inline void __GM_SetPerTaskBase(LIBBASETYPEPTR base)\n"
288 "{\n"
289 " SetTaskStorageSlot(__pertaskslot, (IPTR)base);\n"
290 "}\n"
295 /* Set the size of the library base to accomodate the relbases */
296 if (cfg->options & OPTION_DUPBASE)
298 fprintf(out,
299 "#define LIBBASESIZE (sizeof(struct __GM_DupBase) + sizeof(struct Library *)*%d)\n"
300 , slist_length(cfg->rellibs)
303 } else {
304 fprintf(out,
305 "#define LIBBASESIZE (sizeof(LIBBASETYPE) + sizeof(struct Library *)*%d)\n"
306 , slist_length(cfg->rellibs)
310 if (cfg->rellibs) {
311 struct stringlist *sl;
312 int i, n = slist_length(cfg->rellibs);
314 for (sl=cfg->rellibs; sl; sl=sl->next, n--) {
315 fprintf(out,
316 "#ifndef AROS_RELLIB_OFFSET_%s\n"
317 "# error '%s' is not a relative library\n"
318 "#endif\n"
319 "const IPTR AROS_RELLIB_OFFSET_%s = LIBBASESIZE-sizeof(struct Library *)*%d;\n"
320 , upname(sl->s)
321 , sl->s
322 , upname(sl->s)
328 if (cfg->options & OPTION_DUPBASE) {
329 fprintf(
330 out,
331 "static LONG __GM_BaseSlot;\n"
332 "char *__aros_getoffsettable(void)\n"
333 "{\n"
334 " return (char *)GetTaskStorageSlot(__GM_BaseSlot);\n"
335 "}\n"
336 "void __aros_setoffsettable(void *base)\n"
337 "{\n"
338 " SetTaskStorageSlot(__GM_BaseSlot, (IPTR)base);\n"
339 "}\n"
340 "%s__aros_getbase_%s(void)\n"
341 "{\n"
342 " return (%s)__aros_getoffsettable();\n"
343 "}\n",
344 cfg->libbasetypeptrextern, cfg->libbase,
345 cfg->libbasetypeptrextern
347 } else if (cfg->rellibs || (cfg->options & OPTION_STACKCALL)) {
348 fprintf(out,
349 "#ifdef __aros_getoffsettable\n"
351 if ((cfg->options & OPTION_STACKCALL))
352 fprintf(out,
353 "#error Redefining __aros_setoffsettable is not permitted with stackcall APIs\n"
355 else
356 fprintf(out,
357 "#define __aros_getbase_%s() __aros_getoffsettable()\n",
358 cfg->libbase
360 fprintf(out,
361 "#else /* !__aros_getoffsettable */\n"
362 "static char *__GM_OffsetTable;\n"
363 "char *__aros_getoffsettable(void)\n"
364 "{\n"
365 " return __GM_OffsetTable;\n"
366 "}\n"
367 "BOOL __aros_setoffsettable(char *base)\n"
368 "{\n"
369 " __GM_OffsetTable = base;\n"
370 " return TRUE;\n"
371 "}\n"
372 "%s__aros_getbase_%s(void)\n"
373 "{\n"
374 " return (%s)__aros_getoffsettable();\n"
375 "}\n"
376 "#endif /* __aros_getoffsettable */\n"
377 "\n",
378 cfg->libbasetypeptrextern, cfg->libbase,
379 cfg->libbasetypeptrextern
383 if (cfg->rellibs)
385 struct stringlist *sl;
387 for (sl = cfg->rellibs; sl; sl = sl->next)
389 fprintf(out,
390 "AROS_IMPORT_ASM_SYM(void *,__GM_rellib_base_%s,AROS_RELLIB_BASE_%s);\n"
391 , sl->s
392 , upname(sl->s)
397 for (classlistit = cfg->classlist; classlistit != NULL; classlistit = classlistit->next)
399 /* For the main class basename is the same as the module basename */
400 if (strcmp(classlistit->basename, cfg->basename) == 0)
402 if (classlistit->classptr_var == NULL)
404 fprintf(out,
405 "#if !defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
406 "static APTR GM_UNIQUENAME(%sClass);\n"
407 "#define GM_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
408 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
409 "#define %s_STORE_CLASSPTR 1\n"
410 "#elif defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
411 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_CLASSPTR_FIELD(LIBBASE))\n"
412 "#elif !defined(GM_CLASSPTR_FIELD) && defined(%s_CLASSPTR_FIELD)\n"
413 "#define GM_CLASSPTR_FIELD(LIBBASE) (%s_CLASSPTR_FIELD(LIBBASE))\n"
414 "#endif\n",
415 classlistit->basename,
416 classlistit->basename,
417 classlistit->basename,
418 classlistit->basename, classlistit->basename,
419 classlistit->basename,
420 classlistit->basename,
421 classlistit->basename,
422 classlistit->basename,
423 classlistit->basename
426 else
428 fprintf(out,
429 "#define GM_CLASSPTR_FIELD(LIBBASE) (%s)\n"
430 "#define %s_CLASSPTR_FIELD(LIBBASE) (%s)\n"
431 "#define %s_STORE_CLASSPTR 1\n",
432 classlistit->classptr_var,
433 classlistit->basename, classlistit->classptr_var,
434 classlistit->basename
438 else
440 if (classlistit->classptr_var == NULL)
442 fprintf(out,
443 "#if !defined(%s_CLASSPTR_FIELD)\n"
444 "static APTR GM_UNIQUENAME(%sClass);\n"
445 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
446 "#define %s_STORE_CLASSPTR 1\n"
447 "#endif\n",
448 classlistit->basename,
449 classlistit->basename,
450 classlistit->basename, classlistit->basename,
451 classlistit->basename
454 else
456 fprintf(out,
457 "#define %s_CLASSPTR_FIELD(LIBBASE) (%s)\n"
458 "#define %s_STORE_CLASSPTR 1\n",
459 classlistit->basename, classlistit->classptr_var,
460 classlistit->basename
466 /* Write out the defines for the functions of the function table */
467 writefuncdefs(out, cfg, cfg->funclist);
468 /* Write internal stubs */
469 writefuncinternalstubs(out, cfg, cfg->funclist);
470 fprintf(out, "\n");
473 /* Write out the includes needed for the classes */
474 if (cfg->classlist != NULL)
475 writeboopsiincludes(out);
477 for (classlistit = cfg->classlist; classlistit != NULL; classlistit = classlistit->next)
479 switch (classlistit->classtype)
481 case MUI:
482 case MCC:
483 case MCP:
484 if (!muiinc)
486 writemuiincludes(out);
487 muiinc = 1;
489 /* Fall through: also write boopsi includes */
490 case GADGET:
491 case DATATYPE:
492 case CLASS:
493 case IMAGE:
494 if (!boopsiinc)
496 writeboopsiincludes(out);
497 boopsiinc = 1;
499 break;
500 case HIDD:
501 if (!oopinc)
503 writeoopincludes(out);
504 oopinc = 1;
506 break;
507 default:
508 fprintf(stderr, "Internal error: unhandled classtype in writedecl\n");
509 exit(20);
515 static void writedeclsets(FILE *out, struct config *cfg)
517 /* PROGRAM_ENTRIES is marked as handled but are just ignored in modules */
518 fprintf(out,
519 "THIS_PROGRAM_HANDLES_SYMBOLSET(INIT)\n"
520 "THIS_PROGRAM_HANDLES_SYMBOLSET(EXIT)\n"
521 "DECLARESET(INIT)\n"
522 "DECLARESET(EXIT)\n"
523 "THIS_PROGRAM_HANDLES_SYMBOLSET(PROGRAM_ENTRIES)\n"
524 "DECLARESET(PROGRAM_ENTRIES)\n"
526 if (cfg->modtype != HANDLER)
527 fprintf(out,
528 "THIS_PROGRAM_HANDLES_SYMBOLSET(CTORS)\n"
529 "THIS_PROGRAM_HANDLES_SYMBOLSET(DTORS)\n"
530 "DECLARESET(CTORS)\n"
531 "DECLARESET(DTORS)\n"
532 "THIS_PROGRAM_HANDLES_SYMBOLSET(INIT_ARRAY)\n"
533 "THIS_PROGRAM_HANDLES_SYMBOLSET(FINI_ARRAY)\n"
534 "DECLARESET(INIT_ARRAY)\n"
535 "DECLARESET(FINI_ARRAY)\n"
536 "THIS_PROGRAM_HANDLES_SYMBOLSET(INITLIB)\n"
537 "THIS_PROGRAM_HANDLES_SYMBOLSET(EXPUNGELIB)\n"
538 "DECLARESET(INITLIB)\n"
539 "DECLARESET(EXPUNGELIB)\n"
541 if (!(cfg->options & OPTION_NOAUTOLIB))
543 fprintf(out,
544 "THIS_PROGRAM_HANDLES_SYMBOLSET(LIBS)\n"
545 "DECLARESET(LIBS)\n"
547 if (cfg->rellibs)
548 fprintf(out,
549 "THIS_PROGRAM_HANDLES_SYMBOLSET(RELLIBS)\n"
550 "DECLARESET(RELLIBS)\n"
553 if (!(cfg->options & OPTION_NOOPENCLOSE))
554 fprintf(out,
555 "THIS_PROGRAM_HANDLES_SYMBOLSET(OPENLIB)\n"
556 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLOSELIB)\n"
557 "DECLARESET(OPENLIB)\n"
558 "DECLARESET(CLOSELIB)\n"
560 if (cfg->modtype == DEVICE)
561 fprintf(out,
562 "THIS_PROGRAM_HANDLES_SYMBOLSET(OPENDEV)\n"
563 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLOSEDEV)\n"
564 "DECLARESET(OPENDEV)\n"
565 "DECLARESET(CLOSEDEV)\n"
567 if (cfg->classlist != NULL)
568 fprintf(out,
569 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLASSESINIT)\n"
570 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLASSESEXPUNGE)\n"
571 "DECLARESET(CLASSESINIT)\n"
572 "DECLARESET(CLASSESEXPUNGE)\n"
573 "#define ADD2INITCLASSES(symbol, pri) ADD2SET(symbol, CLASSESINIT, pri)\n"
574 "#define ADD2EXPUNGECLASSES(symbol, pri) ADD2SET(symbol, CLASSESEXPUNGE, pri)\n"
576 fprintf(out, "\n");
580 static void writeresident(FILE *out, struct config *cfg)
582 char *rt_skip = cfg->addromtag;
584 if (rt_skip)
585 fprintf(out, "extern const struct Resident %s;\n", rt_skip);
586 else
588 rt_skip = "GM_UNIQUENAME(End)";
589 fprintf(out, "extern int %s(void);\n", rt_skip);
591 fprintf(out,
592 "extern const APTR GM_UNIQUENAME(FuncTable)[];\n"
594 if (cfg->options & OPTION_RESAUTOINIT)
595 fprintf(out, "static const struct InitTable GM_UNIQUENAME(InitTable);\n");
596 fprintf(out,
597 "\n"
598 "extern const char GM_UNIQUENAME(LibName)[];\n"
599 "extern const char GM_UNIQUENAME(LibID)[];\n"
600 "extern const char GM_UNIQUENAME(Copyright)[];\n"
601 "\n"
604 if (cfg->options & OPTION_RESAUTOINIT)
606 fprintf(out,
607 "#define __freebase(LIBBASE)\\\n"
608 "do {\\\n"
609 " UWORD negsize, possize;\\\n"
610 " UBYTE *negptr = (UBYTE *)LIBBASE;\\\n"
611 " negsize = ((struct Library *)LIBBASE)->lib_NegSize;\\\n"
612 " negptr -= negsize;\\\n"
613 " possize = ((struct Library *)LIBBASE)->lib_PosSize;\\\n"
614 " FreeMem (negptr, negsize+possize);\\\n"
615 "} while(0)\n"
616 "\n");
619 fprintf(out,
620 "AROS_UFP3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
621 " AROS_UFPA(LIBBASETYPEPTR, LIBBASE, D0),\n"
622 " AROS_UFPA(BPTR, segList, A0),\n"
623 " AROS_UFPA(struct ExecBase *, sysBase, A6)\n"
624 ");\n"
626 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
628 fprintf(out,
629 "AROS_LD1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
630 " AROS_LDA(LIBBASETYPEPTR, extralh, D0),\n"
631 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
632 ");\n"
633 "\n",
634 cfg->basename
637 fprintf(out,
638 "__section(\".text.romtag\") struct Resident const GM_UNIQUENAME(ROMTag) =\n"
639 "{\n"
640 " RTC_MATCHWORD,\n"
641 " (struct Resident *)&GM_UNIQUENAME(ROMTag),\n"
642 " (APTR)&%s,\n"
643 " RESIDENTFLAGS,\n"
644 " VERSION_NUMBER,\n",
645 rt_skip
647 switch (cfg->modtype)
649 case LIBRARY:
650 case MUI:
651 case MCC:
652 case MCP:
653 case GADGET:
654 case DATATYPE:
655 case USBCLASS:
656 case HIDD:
657 fprintf(out, " NT_LIBRARY,\n");
658 break;
659 case DEVICE:
660 fprintf(out, " NT_DEVICE,\n");
661 break;
662 case RESOURCE:
663 case HANDLER:
664 fprintf(out, " NT_RESOURCE,\n");
665 break;
666 default:
667 fprintf(stderr, "Internal error: unsupported modtype for NT_...\n");
668 exit(20);
669 break;
671 fprintf(out,
672 " RESIDENTPRI,\n"
673 " (CONST_STRPTR)&GM_UNIQUENAME(LibName)[0],\n"
674 " (CONST_STRPTR)&GM_UNIQUENAME(LibID)[6],\n"
676 if (cfg->options & OPTION_RESAUTOINIT)
678 fprintf(out,
679 " (APTR)&GM_UNIQUENAME(InitTable)\n"
680 "};\n"
681 "\n"
682 "__section(\".text.romtag\") static struct InitTable\n"
683 "{\n"
684 " IPTR Size;\n"
685 " const APTR *FuncTable;\n"
686 " struct DataTable *DataTable;\n"
687 " APTR InitLibTable;\n"
688 "}\n"
689 "const GM_UNIQUENAME(InitTable) =\n"
690 "{\n"
691 " LIBBASESIZE,\n"
692 " &GM_UNIQUENAME(FuncTable)[0],\n"
693 " NULL,\n"
694 " (APTR)GM_UNIQUENAME(InitLib)\n"
695 "};\n"
698 else
699 fprintf(out, " (APTR)GM_UNIQUENAME(InitLib)\n};\n");
701 fprintf(out,
702 "\n"
703 "__section(\".text.romtag\") const char GM_UNIQUENAME(LibName)[] = MOD_NAME_STRING;\n"
704 "__section(\".text.romtag\") const char GM_UNIQUENAME(LibID)[] = VERSION_STRING;\n"
705 "__section(\".text.romtag\") const char GM_UNIQUENAME(Copyright)[] = COPYRIGHT_STRING;\n"
706 "\n"
710 static void writehandler(FILE *out, struct config *cfg)
712 int i, handlers=0;
713 struct handlerinfo *hl;
714 int need_fse = 0, need_dos = 0;
716 fprintf(out,
717 "\n"
718 "#include <resources/filesysres.h>\n"
719 "#include <aros/system.h>\n"
720 "#include <proto/arossupport.h>\n"
721 "#include <proto/expansion.h>\n"
722 "\n"
725 for (hl = cfg->handlerlist; hl != NULL; hl = hl->next) {
726 if (hl->type == HANDLER_DOSNODE)
727 need_dos = 1;
728 else
729 need_fse = 1;
730 handlers++;
733 fprintf(out,
734 "\n"
735 "LONG %s(struct ExecBase *sysBase);\n"
736 "extern const LONG __aros_libreq_SysBase __attribute__((weak));\n"
737 "\n"
738 "__startup AROS_PROCH(GM_UNIQUENAME(Handler), argptr, argsize, SysBase)\n"
739 "{\n"
740 " AROS_PROCFUNC_INIT\n"
741 "\n"
742 " LONG ret = RETURN_FAIL;\n"
743 "\n"
744 " if (!SysBase || SysBase->LibNode.lib_Version < __aros_libreq_SysBase)\n"
745 " return ERROR_INVALID_RESIDENT_LIBRARY;\n"
746 " if (set_call_funcs(SETNAME(INIT), 1, 1)) {\n"
747 " ret = %s(SysBase);\n"
748 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
749 " }\n"
750 "\n"
751 " return ret;\n"
752 "\n"
753 " AROS_PROCFUNC_EXIT\n"
754 "}\n"
755 , cfg->handlerfunc
756 , cfg->handlerfunc
759 fprintf(out,
760 "\n"
761 "static inline BOOL GM_UNIQUENAME(InitHandler)(struct ExecBase *SysBase)\n"
762 "{\n"
765 if (!need_dos && !need_fse) {
766 fprintf(out,
767 " return TRUE;\n"
768 "}\n"
770 return;
773 fprintf(out,
774 " BPTR seg;\n"
777 if (need_dos) {
778 fprintf(out,
779 " struct Library *ExpansionBase;\n"
782 if (need_fse) {
783 fprintf(out,
784 " struct FileSysResource *fsr;\n"
785 " struct FileSysEntry *fse;\n"
788 if (need_fse) {
789 fprintf(out,
790 " fsr = (struct FileSysResource *)OpenResource(\"FileSystem.resource\");\n"
791 " if (fsr == NULL)\n"
792 " return FALSE;\n"
795 if (need_dos) {
796 fprintf(out,
797 " ExpansionBase = OpenLibrary(\"expansion.library\", 36);\n"
798 " if (ExpansionBase == NULL)\n"
799 " return FALSE;\n"
802 fprintf(out,
803 " seg = CreateSegList(GM_UNIQUENAME(Handler));\n"
804 " if (seg != BNULL) {\n"
806 for (hl = cfg->handlerlist; hl != NULL; hl = hl->next)
808 switch (hl->type)
810 case HANDLER_DOSNODE:
811 fprintf(out,
812 "\n"
813 " {\n"
814 " struct DeviceNode *node;\n"
815 " IPTR pp[] = { \n"
816 " (IPTR)\"%s\",\n"
817 " (IPTR)NULL,\n"
818 " (IPTR)0,\n"
819 " (IPTR)0,\n"
820 " (IPTR)0\n"
821 " };\n"
822 " node = MakeDosNode((APTR)pp);\n"
823 " if (node) {\n"
824 " node->dn_StackSize = %u;\n"
825 " node->dn_SegList = seg;\n"
826 " node->dn_Startup = (BPTR)%d;\n"
827 " node->dn_Priority = %d;\n"
828 " node->dn_GlobalVec = (BPTR)(SIPTR)-1;\n"
829 " AddBootNode(%d, 0, node, NULL);\n"
830 " }\n"
831 " }\n"
832 "\n"
833 , hl->name
834 , hl->stacksize
835 , hl->startup
836 , hl->priority
837 , hl->bootpri
839 break;
840 case HANDLER_RESIDENT:
841 case HANDLER_DOSTYPE:
842 fprintf(out,
843 "\n"
844 " /* Check to see if we can allocate the memory for the fse */\n"
845 " fse = AllocMem(sizeof(*fse), MEMF_CLEAR);\n"
846 " if (fse) {\n"
847 " fse->fse_Node.ln_Name = VERSION_STRING;\n"
848 " fse->fse_Node.ln_Pri = %d;\n"
849 " fse->fse_DosType = 0x%08x;\n"
850 " fse->fse_Version = (MAJOR_VERSION << 16) | MINOR_VERSION;\n"
851 " fse->fse_PatchFlags = FSEF_SEGLIST | FSEF_GLOBALVEC | FSEF_PRIORITY;\n"
852 , hl->autodetect
853 , hl->id
855 if (hl->stacksize)
857 fprintf(out,
858 " fse->fse_PatchFlags |= FSEF_STACKSIZE;\n"
859 " fse->fse_StackSize = %d;\n"
860 , hl->stacksize
863 if (hl->name)
864 fprintf(out,
865 " fse->fse_PatchFlags |= FSEF_HANDLER;\n"
866 " fse->fse_Handler = AROS_CONST_BSTR(\"%s\");\n"
867 , hl->name);
868 fprintf(out,
869 " fse->fse_Priority = %d;\n"
870 " fse->fse_SegList = seg;\n"
871 " fse->fse_GlobalVec = (BPTR)(SIPTR)-1;\n"
872 " fse->fse_Startup = (BPTR)%d;\n"
873 "\n"
874 " /* Add to the list. I know forbid and permit are\n"
875 " * a little unnecessary for the pre-multitasking state\n"
876 " * we should be in at this point, but you never know\n"
877 " * who's going to blindly copy this code as an example.\n"
878 " */\n"
879 " Forbid();\n"
880 " Enqueue(&fsr->fsr_FileSysEntries, (struct Node *)fse);\n"
881 " Permit();\n"
882 " }\n"
883 , hl->priority
884 , hl->startup
886 break;
889 fprintf(out,
890 " }\n"
892 if (need_dos) {
893 fprintf(out,
894 " CloseLibrary(ExpansionBase);\n"
897 fprintf(out,
898 " return TRUE;\n"
899 "}\n"
900 "\n"
904 static void writeinitlib(FILE *out, struct config *cfg)
906 if (cfg->handlerlist)
907 writehandler(out, cfg);
909 fprintf(out,
910 "extern const LONG __aros_libreq_SysBase __attribute__((weak));\n"
911 "\n"
912 "AROS_UFH3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
913 " AROS_UFHA(LIBBASETYPEPTR, LIBBASE, D0),\n"
914 " AROS_UFHA(BPTR, segList, A0),\n"
915 " AROS_UFHA(struct ExecBase *, sysBase, A6)\n"
916 ")\n"
917 "{\n"
918 " AROS_USERFUNC_INIT\n"
921 if (cfg->modtype == HANDLER) {
922 fprintf(out,
923 "\n"
924 " GM_UNIQUENAME(InitHandler)(sysBase);\n"
925 " return LIBBASE;\n"
926 "\n"
927 " AROS_USERFUNC_EXIT\n"
928 "}\n"
929 "\n"
931 return;
934 fprintf(out,
935 "\n"
936 " int ok;\n"
937 " int initcalled = 0;\n"
939 /* Set the global SysBase, needed for __aros_setoffsettable()/__aros_getoffsettable() */
940 if (cfg->options & OPTION_DUPBASE)
941 fprintf(out,
942 " SysBase = sysBase;\n"
944 else
945 fprintf(out,
946 " struct ExecBase *SysBase = sysBase;\n"
948 fprintf(out,
949 "\n"
950 "#ifdef GM_SYSBASE_FIELD\n"
951 " GM_SYSBASE_FIELD(LIBBASE) = (APTR)SysBase;\n"
952 "#endif\n"
953 " if (!SysBase || SysBase->LibNode.lib_Version < __aros_libreq_SysBase)\n"
954 " return NULL;\n"
955 "\n"
958 if (cfg->options & OPTION_RESAUTOINIT) {
959 fprintf(out,
960 "#ifdef GM_OOPBASE_FIELD\n"
961 " GM_OOPBASE_FIELD(LIBBASE) = OpenLibrary(\"oop.library\",0);\n"
962 " if (GM_OOPBASE_FIELD(LIBBASE) == NULL)\n"
963 " return NULL;\n"
964 "#endif\n"
968 if (!(cfg->options & OPTION_RESAUTOINIT))
970 fprintf(out,
971 " int vecsize;\n"
972 " struct Node *n;\n"
973 " char *mem;\n"
974 "\n"
975 " vecsize = FUNCTIONS_COUNT * LIB_VECTSIZE;\n"
976 " if (vecsize > 0)\n"
977 " vecsize = ((vecsize-1)/sizeof(IPTR) + 1)*sizeof(IPTR);\n"
978 " mem = AllocMem(vecsize+sizeof(LIBBASETYPE), MEMF_PUBLIC|MEMF_CLEAR);\n"
979 " if (mem == NULL)\n"
980 " return NULL;\n"
981 " LIBBASE = (LIBBASETYPEPTR)(mem + vecsize);\n"
982 " n = (struct Node *)LIBBASE;\n"
983 " n->ln_Type = NT_RESOURCE;\n"
984 " n->ln_Pri = RESIDENTPRI;\n"
985 " n->ln_Name = (char *)GM_UNIQUENAME(LibName);\n"
986 " MakeFunctions(LIBBASE, (APTR)GM_UNIQUENAME(FuncTable), NULL);\n"
988 if ((cfg->modtype != RESOURCE) && (cfg->options & OPTION_SELFINIT))
990 fprintf(out,
991 " ((struct Library*)LIBBASE)->lib_NegSize = vecsize;\n"
992 " ((struct Library*)LIBBASE)->lib_PosSize = sizeof(LIBBASETYPE);\n"
997 else
999 fprintf(out,
1000 " ((struct Library *)LIBBASE)->lib_Revision = REVISION_NUMBER;\n"
1004 if (cfg->options & OPTION_DUPBASE)
1005 fprintf(out,
1006 " __GM_BaseSlot = AllocTaskStorageSlot();\n"
1007 " if (!SetTaskStorageSlot(__GM_BaseSlot, (IPTR)LIBBASE)) {\n"
1008 " FreeTaskStorageSlot(__GM_BaseSlot);\n"
1009 " return NULL;\n"
1010 " }\n"
1012 else if (cfg->rellibs || (cfg->options & OPTION_STACKCALL))
1013 fprintf(out,
1014 " __aros_setoffsettable((char *)LIBBASE);\n"
1016 if (cfg->options & OPTION_PERTASKBASE)
1017 fprintf(out,
1018 " __pertaskslot = AllocTaskStorageSlot();\n"
1021 if (!(cfg->options & OPTION_NOEXPUNGE) && cfg->modtype!=RESOURCE)
1022 fprintf(out, " GM_SEGLIST_FIELD(LIBBASE) = segList;\n");
1023 if (cfg->options & OPTION_DUPBASE)
1024 fprintf(out, " GM_ROOTBASE_FIELD(LIBBASE) = (LIBBASETYPEPTR)LIBBASE;\n");
1025 fprintf(out, " if (");
1026 if (!(cfg->options & OPTION_NOAUTOLIB))
1027 fprintf(out, "set_open_libraries() && ");
1028 if (cfg->rellibs)
1029 fprintf(out, "set_open_rellibraries(LIBBASE) && ");
1030 fprintf(out,
1031 "set_call_funcs(SETNAME(INIT), 1, 1) &&"
1033 if (cfg->classlist != NULL)
1034 fprintf(out, "set_call_libfuncs(SETNAME(CLASSESINIT), 1, 1, LIBBASE) && ");
1035 fprintf(out,
1036 "1)\n"
1037 " {\n"
1038 " set_call_funcs(SETNAME(CTORS), -1, 0);\n"
1039 " set_call_funcs(SETNAME(INIT_ARRAY), 1, 0);\n"
1040 "\n"
1043 fprintf(out,
1044 " initcalled = 1;\n"
1045 " ok = set_call_libfuncs(SETNAME(INITLIB), 1, 1, LIBBASE);\n"
1046 " }\n"
1047 " else\n"
1048 " ok = 0;\n"
1049 "\n"
1050 " if (!ok)\n"
1051 " {\n"
1052 " if (initcalled)\n"
1053 " set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 0, LIBBASE);\n"
1054 " set_call_funcs(SETNAME(FINI_ARRAY), -1, 0);\n"
1055 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
1056 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
1058 if (cfg->classlist != NULL)
1059 fprintf(out, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, LIBBASE);\n");
1060 if (cfg->rellibs)
1061 fprintf(out, " set_close_rellibraries(LIBBASE);\n");
1062 if (!(cfg->options & OPTION_NOAUTOLIB))
1063 fprintf(out, " set_close_libraries();\n");
1065 if (cfg->options & OPTION_RESAUTOINIT)
1067 fprintf(out,
1068 "\n"
1069 " __freebase(LIBBASE);\n"
1072 else
1074 fprintf(out,
1075 "\n"
1076 " FreeMem(mem, vecsize+LIBBASESIZE);\n"
1079 fprintf(out,
1080 " return NULL;\n"
1081 " }\n"
1082 " else\n"
1083 " {\n"
1086 if (!(cfg->options & OPTION_RESAUTOINIT) && !(cfg->options & OPTION_SELFINIT))
1088 switch (cfg->modtype)
1090 case RESOURCE:
1091 fprintf(out, " AddResource(LIBBASE);\n");
1092 break;
1094 case DEVICE:
1095 fprintf(out, " AddDevice(LIBBASE);\n");
1097 default:
1098 /* Everything else is library */
1099 fprintf(out, " AddLibrary(LIBBASE);\n");
1100 break;
1104 fprintf(out,
1105 " return LIBBASE;\n"
1106 " }\n"
1107 "\n"
1108 " AROS_USERFUNC_EXIT\n"
1109 "}\n"
1110 "\n"
1114 static void writeopenlib(FILE *out, struct config *cfg)
1116 switch (cfg->modtype)
1118 case RESOURCE:
1119 fprintf(stderr, "Internal error: writeopenlib called for a resource\n");
1120 break;
1121 case HANDLER:
1122 fprintf(stderr, "Internal error: writeopenlib called for a handler\n");
1123 break;
1124 case DEVICE:
1125 if (cfg->options & OPTION_NOOPENCLOSE)
1126 fprintf(out,
1127 "AROS_LD3 (void, GM_UNIQUENAME(OpenLib),\n"
1128 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1129 " AROS_LDA(ULONG, unitnum, D0),\n"
1130 " AROS_LDA(ULONG, flags, D1),\n"
1131 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1132 ");\n",
1133 cfg->basename
1135 else
1137 fprintf(out,
1138 "AROS_LH3 (void, GM_UNIQUENAME(OpenLib),\n"
1139 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1140 " AROS_LHA(IPTR, unitnum, D0),\n"
1141 " AROS_LHA(ULONG, flags, D1),\n"
1142 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1143 ")\n",
1144 cfg->basename
1146 fprintf(out,
1147 "{\n"
1148 " AROS_LIBFUNC_INIT\n"
1149 "\n"
1150 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, LIBBASE)\n"
1151 " && set_call_devfuncs(SETNAME(OPENDEV), 1, 1, LIBBASE, ioreq, unitnum, flags)\n"
1152 " )\n"
1153 " {\n"
1154 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1155 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1156 "\n"
1157 " ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;\n"
1158 " }\n"
1159 " else\n"
1160 " {\n"
1161 " if (ioreq->io_Error >= 0)\n"
1162 " ioreq->io_Error = IOERR_OPENFAIL;\n"
1163 " }\n"
1164 "\n"
1165 " return;\n"
1166 "\n"
1167 " AROS_LIBFUNC_EXIT\n"
1168 "}\n"
1169 "\n"
1172 break;
1173 default:
1174 if (cfg->options & OPTION_NOOPENCLOSE)
1176 fprintf(out,
1177 "AROS_LD1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
1178 " AROS_LDA (ULONG, version, D0),\n"
1179 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1180 ");\n",
1181 cfg->basename
1183 return;
1185 fprintf(out,
1186 "AROS_LH1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
1187 " AROS_LHA (ULONG, version, D0),\n"
1188 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1189 ")\n"
1190 "{\n"
1191 " AROS_LIBFUNC_INIT\n"
1192 "\n",
1193 cfg->basename
1195 if (!(cfg->options & OPTION_DUPBASE))
1197 fprintf(out,
1198 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, LIBBASE) )\n"
1199 " {\n"
1200 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1201 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1202 " return LIBBASE;\n"
1203 " }\n"
1204 "\n"
1205 " return NULL;\n"
1206 "\n"
1207 " AROS_LIBFUNC_EXIT\n"
1208 "}\n"
1209 "\n"
1212 else /* OPTION_DUPBASE */
1214 fprintf(out,
1215 " struct Library *newlib = NULL;\n"
1216 " UWORD possize = ((struct Library *)LIBBASE)->lib_PosSize;\n"
1217 " LIBBASETYPEPTR oldbase = (LIBBASETYPEPTR)__aros_getbase_%s();\n",
1218 cfg->libbase
1220 if (cfg->options & OPTION_PERTASKBASE)
1221 fprintf(out,
1222 " struct Task *thistask = FindTask(NULL);\n"
1223 " LIBBASETYPEPTR oldpertaskbase = __GM_GetPerTaskBase();\n"
1224 " if (!oldpertaskbase)\n"
1225 " oldpertaskbase = __GM_GetParentPerTaskBase();\n"
1226 " newlib = (struct Library *)oldpertaskbase;\n"
1227 " if (newlib)\n"
1228 " {\n"
1229 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1230 " if (dupbase->task != thistask)\n"
1231 " newlib = NULL;\n"
1232 " else if (thistask->tc_Node.ln_Type == NT_PROCESS\n"
1233 " && dupbase->retaddr != ((struct Process *)thistask)->pr_ReturnAddr\n"
1234 " )\n"
1235 " newlib = NULL;\n"
1236 " else\n"
1237 " dupbase->taskopencount++;\n"
1238 " }\n"
1241 fprintf(out,
1242 "\n"
1243 " if (newlib == NULL)\n"
1244 " {\n"
1245 " newlib = MakeLibrary(GM_UNIQUENAME(InitTable).FuncTable,\n"
1246 " GM_UNIQUENAME(InitTable).DataTable,\n"
1247 " NULL,\n"
1248 " GM_UNIQUENAME(InitTable).Size,\n"
1249 " (BPTR)NULL\n"
1250 " );\n"
1251 " if (newlib == NULL)\n"
1252 " return NULL;\n"
1253 "\n"
1254 " CopyMem(LIBBASE, newlib, possize);\n"
1255 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1256 " dupbase->oldbase = oldbase;\n"
1257 " __aros_setoffsettable((char *)newlib);\n"
1259 if (cfg->options & OPTION_PERTASKBASE)
1260 fprintf(out,
1261 " dupbase->task = thistask;\n"
1262 " if (thistask->tc_Node.ln_Type == NT_PROCESS)\n"
1263 " dupbase->retaddr = ((struct Process *)thistask)->pr_ReturnAddr;\n"
1264 " dupbase->oldpertaskbase = oldpertaskbase;\n"
1265 " dupbase->taskopencount = 1;\n"
1266 " __GM_SetPerTaskBase((LIBBASETYPEPTR)newlib);\n"
1268 fprintf(out,
1269 "\n"
1270 " if (!(set_open_rellibraries(newlib)\n"
1271 " && set_call_libfuncs(SETNAME(OPENLIB), 1, 1, newlib)\n"
1272 " )\n"
1273 " )\n"
1274 " {\n");
1275 if (cfg->options & OPTION_PERTASKBASE)
1276 fprintf(out,
1277 " __GM_SetPerTaskBase(oldpertaskbase);\n");
1278 fprintf(out,
1279 " __freebase(newlib);\n"
1280 " return NULL;\n"
1281 " }\n"
1282 "\n"
1283 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1284 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1285 " }\n"
1286 "\n"
1287 " return (LIBBASETYPEPTR)newlib;\n"
1288 "\n"
1289 " AROS_LIBFUNC_EXIT\n"
1290 "}\n"
1291 "\n"
1298 static void writecloselib(FILE *out, struct config *cfg)
1300 if (cfg->options & OPTION_NOOPENCLOSE)
1302 if (cfg->modtype != DEVICE)
1303 fprintf(out,
1304 "AROS_LD0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1305 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1306 ");\n",
1307 cfg->basename
1309 else
1310 fprintf(out,
1311 "AROS_LD1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1312 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1313 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1314 ");\n",
1315 cfg->basename
1317 return;
1319 if (cfg->modtype != DEVICE)
1320 fprintf(out,
1321 "AROS_LH0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1322 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1323 ")\n",
1324 cfg->basename
1326 else
1327 fprintf(out,
1328 "AROS_LH1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1329 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1330 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1331 ")\n",
1332 cfg->basename
1335 fprintf(out,
1336 "{\n"
1337 " AROS_LIBFUNC_INIT\n"
1338 "\n"
1340 if (cfg->modtype == DEVICE)
1341 fprintf(out,
1342 " if (!set_call_devfuncs(SETNAME(CLOSEDEV), -1, 1, LIBBASE, ioreq, 0, 0))\n"
1343 " {\n"
1344 " return BNULL;\n"
1345 " }\n"
1347 if (!(cfg->options & OPTION_DUPBASE))
1349 fprintf(out,
1350 " ((struct Library *)LIBBASE)->lib_OpenCnt--;\n"
1351 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, LIBBASE);\n"
1354 else /* OPTION_DUPBASE */
1356 fprintf(out,
1357 " LIBBASETYPEPTR rootbase = GM_ROOTBASE_FIELD(LIBBASE);\n"
1358 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)LIBBASE;\n"
1359 " __aros_setoffsettable(LIBBASE);\n"
1361 if (cfg->options & OPTION_PERTASKBASE)
1362 fprintf(out,
1363 " dupbase->taskopencount--;\n"
1364 " if (dupbase->taskopencount != 0)\n"
1365 " return BNULL;\n"
1367 fprintf(out,
1368 "\n"
1369 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, LIBBASE);\n"
1370 " set_close_rellibraries(LIBBASE);\n"
1371 " __aros_setoffsettable((char *)dupbase->oldbase);\n"
1373 if (cfg->options & OPTION_PERTASKBASE)
1374 fprintf(out,
1375 " __GM_SetPerTaskBase(((struct __GM_DupBase *)LIBBASE)->oldpertaskbase);\n"
1377 fprintf(out,
1378 " __freebase(LIBBASE);\n"
1379 " LIBBASE = rootbase;\n"
1380 " ((struct Library *)LIBBASE)->lib_OpenCnt--;\n"
1381 "\n"
1384 if (!(cfg->options & OPTION_NOEXPUNGE))
1385 fprintf(out,
1386 " if\n"
1387 " (\n"
1388 " (((struct Library *)LIBBASE)->lib_OpenCnt == 0)\n"
1389 " && (((struct Library *)LIBBASE)->lib_Flags & LIBF_DELEXP)\n"
1390 " )\n"
1391 " {\n"
1392 " return AROS_LC1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1393 " AROS_LCA(LIBBASETYPEPTR, LIBBASE, D0),\n"
1394 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
1395 " );\n"
1396 " }\n",
1397 cfg->basename
1399 fprintf(out,
1400 "\n"
1401 " return BNULL;\n"
1402 "\n"
1403 " AROS_LIBFUNC_EXIT\n"
1404 "}\n"
1405 "\n"
1410 static void writeexpungelib(FILE *out, struct config *cfg)
1412 fprintf(out,
1413 "AROS_LH1 (BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1414 " AROS_LHA(LIBBASETYPEPTR, extralh, D0),\n"
1415 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
1416 ")\n",
1417 cfg->basename
1419 fprintf(out,
1420 "{\n"
1421 " AROS_LIBFUNC_INIT\n"
1422 "\n"
1424 if (!(cfg->options & OPTION_NOEXPUNGE))
1426 if (cfg->options & OPTION_RESAUTOINIT) {
1427 fprintf(out,
1428 "#ifdef GM_SYSBASE_FIELD\n"
1429 " struct ExecBase *SysBase = (struct ExecBase *)GM_SYSBASE_FIELD(LIBBASE);\n"
1430 "#endif\n"
1433 if (cfg->options & OPTION_DUPBASE)
1434 fprintf(out, " __aros_setoffsettable(LIBBASE);\n");
1435 fprintf(out,
1436 "\n"
1437 " if ( ((struct Library *)LIBBASE)->lib_OpenCnt == 0 )\n"
1438 " {\n"
1439 " BPTR seglist = GM_SEGLIST_FIELD(LIBBASE);\n"
1440 "\n"
1441 " if(!set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 1, LIBBASE))\n"
1442 " {\n"
1443 " ((struct Library *)LIBBASE)->lib_Flags |= LIBF_DELEXP;\n"
1444 " return BNULL;\n"
1445 " }\n"
1446 "\n"
1447 " Remove((struct Node *)LIBBASE);\n"
1448 "\n"
1449 " set_call_funcs(SETNAME(FINI_ARRAY), -1, 0);\n"
1450 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
1451 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
1453 if (cfg->classlist != NULL)
1454 fprintf(out, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, LIBBASE);\n");
1455 if (cfg->rellibs)
1456 fprintf(out, " set_close_rellibraries(LIBBASE);\n");
1457 if (!(cfg->options & OPTION_NOAUTOLIB))
1458 fprintf(out, " set_close_libraries();\n"
1459 "#ifdef GM_OOPBASE_FIELD\n"
1460 " CloseLibrary((struct Library *)GM_OOPBASE_FIELD(LIBBASE));\n"
1461 "#endif\n"
1463 if (cfg->options & OPTION_PERTASKBASE)
1464 fprintf(out,
1465 " FreeTaskStorageSlot(__pertaskslot);\n"
1466 " __pertaskslot = 0;\n"
1468 fprintf(out,
1469 "\n"
1470 " __freebase(LIBBASE);\n"
1471 "\n"
1472 " return seglist;\n"
1473 " }\n"
1474 "\n"
1475 " ((struct Library *)LIBBASE)->lib_Flags |= LIBF_DELEXP;\n"
1478 fprintf(out,
1479 "\n"
1480 " return BNULL;\n"
1481 "\n"
1482 " AROS_LIBFUNC_EXIT\n"
1483 "}\n"
1484 "\n"
1489 static void writeextfunclib(FILE *out, struct config *cfg)
1491 fprintf(out,
1492 "AROS_LH0 (LIBBASETYPEPTR, GM_UNIQUENAME(ExtFuncLib),\n"
1493 " LIBBASETYPEPTR, LIBBASE, 4, %s\n"
1494 ")\n"
1495 "{\n"
1496 " AROS_LIBFUNC_INIT\n"
1497 " return NULL;\n"
1498 " AROS_LIBFUNC_EXIT\n"
1499 "}\n"
1500 "\n",
1501 cfg->basename
1506 static void
1507 writefunctable(FILE *out,
1508 struct config *cfg
1511 struct functionhead *funclistit = cfg->funclist;
1512 struct functionarg *arglistit;
1513 unsigned int lvo;
1514 int i;
1515 char *name, *type;
1516 int lastversion = 0;
1518 /* lvo contains the number of functions already printed in the functable */
1519 lvo = 0;
1521 if (!(cfg->options & OPTION_NORESIDENT))
1523 fprintf(out,
1524 "\n"
1525 "__section(\".text.romtag\") const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1526 "{\n"
1528 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
1530 fprintf(out,
1531 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(OpenLib),%s,1),\n"
1532 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(CloseLib),%s,2),\n"
1533 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExpungeLib),%s,3),\n"
1534 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExtFuncLib),%s,4),\n",
1535 cfg->basename, cfg->basename, cfg->basename, cfg->basename
1537 lvo += 4;
1539 if (cfg->modtype == MCC || cfg->modtype == MUI || cfg->modtype == MCP)
1541 lvo++;
1542 fprintf(out,
1543 " &AROS_SLIB_ENTRY(MCC_Query,%s,%d),\n",
1544 cfg->basename, lvo
1547 else if (cfg->modtype == DATATYPE)
1549 lvo++;
1550 fprintf(out,
1551 " &AROS_SLIB_ENTRY(ObtainEngine,%s,%d),\n",
1552 cfg->basename, lvo
1556 else /* NORESIDENT */
1558 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
1560 int neednull = 0;
1561 struct functionhead *funclistit2;
1563 if (funclistit->lvo != 1)
1565 fprintf(stderr, "Module without a generated resident structure has to provide the Open function (LVO==1)\n");
1566 exit(20);
1568 else
1569 funclistit = funclistit->next;
1571 if (funclistit->lvo != 2)
1573 fprintf(stderr, "Module without a generated resident structure has to provide the Close function (LVO==2)\n");
1574 exit(20);
1576 else
1577 funclistit = funclistit->next;
1579 if (funclistit->lvo == 3)
1580 funclistit = funclistit->next;
1581 else
1582 neednull = 1;
1584 if (funclistit->lvo == 4)
1585 funclistit = funclistit->next;
1586 else
1587 neednull = 1;
1589 if (neednull)
1590 fprintf(out,
1591 "\n"
1592 "AROS_UFH1S(int, %s_null,\n"
1593 " AROS_UFHA(struct Library *, libbase, A6)\n"
1594 ")\n"
1595 "{\n"
1596 " AROS_USERFUNC_INIT\n"
1597 " return 0;\n"
1598 " AROS_USERFUNC_EXIT\n"
1599 "}\n",
1600 cfg->modulename
1603 funclistit = cfg->funclist;
1604 funclistit2 = funclistit->next;
1605 fprintf(out,
1606 "\n"
1607 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1608 "{\n"
1609 " &AROS_SLIB_ENTRY(%s,%s,%d),\n"
1610 " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1611 funclistit->internalname, cfg->basename, lvo+1,
1612 funclistit2->internalname, cfg->basename, lvo+2
1614 lvo += 2;
1615 funclistit = funclistit2->next;
1617 if (funclistit->lvo == 3)
1619 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1620 funclistit->internalname, cfg->basename, lvo+1
1622 funclistit = funclistit->next;
1624 else
1625 fprintf(out, " &%s_null,\n", cfg->modulename);
1626 lvo++;
1628 if (funclistit->lvo == 4)
1630 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1631 funclistit->internalname, cfg->basename, lvo+1
1633 funclistit = funclistit->next;
1635 else
1636 fprintf(out, " &%s_null,\n", cfg->modulename);
1637 lvo++;
1639 else
1641 fprintf(out,
1642 "\n"
1643 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1644 "{\n");
1648 while (funclistit != NULL)
1650 for (i = lvo+1; i<funclistit->lvo; i++)
1651 fprintf(out, " NULL,\n");
1652 lvo = funclistit->lvo;
1654 switch (funclistit->libcall)
1656 case STACK:
1657 case REGISTER:
1658 case REGISTERMACRO:
1659 if (funclistit->version != lastversion) {
1660 lastversion = funclistit->version;
1661 fprintf(out, " /* Version %d */\n", lastversion);
1663 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n", funclistit->internalname, cfg->basename, lvo);
1664 break;
1666 default:
1667 fprintf(stderr, "Internal error: unhandled libcall type in writestart\n");
1668 exit(20);
1669 break;
1672 funclistit = funclistit->next;
1675 fprintf(out, " (void *)-1\n};\n");
1679 static void writesets(FILE *out, struct config *cfg)
1681 fprintf(out,
1682 "DEFINESET(INIT)\n"
1683 "DEFINESET(EXIT)\n"
1685 if (cfg->modtype != HANDLER)
1686 fprintf(out,
1687 "DEFINESET(CTORS)\n"
1688 "DEFINESET(DTORS)\n"
1689 "DEFINESET(INIT_ARRAY)\n"
1690 "DEFINESET(FINI_ARRAY)\n"
1691 "DEFINESET(INITLIB)\n"
1692 "DEFINESET(EXPUNGELIB)\n"
1694 if (!(cfg->options & OPTION_NOOPENCLOSE))
1695 fprintf(out,
1696 "DEFINESET(OPENLIB)\n"
1697 "DEFINESET(CLOSELIB)\n"
1699 if (cfg->modtype == DEVICE)
1700 fprintf(out,
1701 "DEFINESET(OPENDEV)\n"
1702 "DEFINESET(CLOSEDEV)\n"
1704 if (cfg->classlist != NULL)
1705 fprintf(out,
1706 "DEFINESET(CLASSESINIT)\n"
1707 "DEFINESET(CLASSESEXPUNGE)\n"
1709 fprintf(out, "\n");