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