Fix create_patch macro.
[AROS.git] / tools / genmodule / writestart.c
blob8ed2a43130ea3500e102d17ca0864fe61b95e982
1 /*
2 Copyright © 1995-2011, 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 "#ifdef SysBase\n"
204 "#undef SysBase\n"
205 "#endif\n"
206 "#ifdef OOPBase\n"
207 "#undef OOPBase\n"
208 "#endif\n"
209 "\n"
210 "#include <proto/exec.h>\n"
211 "#include <proto/alib.h>\n"
212 "\n"
215 /* Write out declaration section provided in the config file */
216 for (linelistit = cfg->cdeflines; linelistit != NULL; linelistit = linelistit->next)
218 fprintf(out, "%s\n", linelistit->s);
221 /* Is there a variable for storing the segList ? */
222 if (!(cfg->options & OPTION_NOEXPUNGE) && cfg->modtype!=RESOURCE && cfg->modtype != HANDLER)
224 fprintf(out,
225 "#ifndef GM_SEGLIST_FIELD\n"
226 "static BPTR __attribute__((unused)) GM_UNIQUENAME(seglist);\n"
227 "#define GM_SEGLIST_FIELD(LIBBASE) (GM_UNIQUENAME(seglist))\n"
228 "#endif\n"
231 if (cfg->options & OPTION_DUPBASE)
232 fprintf(out,
233 "/* Required for TaskStorage manipulation */\n"
234 "extern struct ExecBase *SysBase;\n"
236 if (cfg->options & OPTION_DUPBASE)
238 fprintf(out,
239 "#ifndef GM_ROOTBASE_FIELD\n"
240 "static LIBBASETYPEPTR GM_UNIQUENAME(rootbase);\n"
241 "#define GM_ROOTBASE_FIELD(LIBBASE) (GM_UNIQUENAME(rootbase))\n"
242 "#endif\n"
243 "struct __GM_DupBase {\n"
244 " LIBBASETYPE base;\n"
245 " LIBBASETYPEPTR oldbase;\n"
247 if (cfg->options & OPTION_PERTASKBASE)
249 fprintf(out,
250 " ULONG taskopencount;\n"
251 " struct Task *task;\n"
252 " APTR retaddr;\n"
253 " LIBBASETYPEPTR oldpertaskbase;\n"
256 fprintf(out,
257 "};\n"
259 if (cfg->options & OPTION_PERTASKBASE)
261 fprintf(out,
262 "static LONG __pertaskslot;\n"
263 "LIBBASETYPEPTR __GM_GetBaseParent(LIBBASETYPEPTR base)\n"
264 "{\n"
265 " return ((struct __GM_DupBase *)base)->oldpertaskbase;\n"
266 "}\n"
267 "static inline LIBBASETYPEPTR __GM_GetPerTaskBase(void)\n"
268 "{\n"
269 " return (LIBBASETYPEPTR)GetTaskStorageSlot(__pertaskslot);\n"
270 "}\n"
271 "static inline void __GM_SetPerTaskBase(LIBBASETYPEPTR base)\n"
272 "{\n"
273 " SetTaskStorageSlot(__pertaskslot, (IPTR)base);\n"
274 "}\n"
279 /* Set the size of the library base to accomodate the relbases */
280 if (cfg->options & OPTION_DUPBASE)
282 fprintf(out,
283 "#define LIBBASESIZE (sizeof(struct __GM_DupBase) + sizeof(struct Library *)*%d)\n"
284 , slist_length(cfg->rellibs)
287 } else {
288 fprintf(out,
289 "#define LIBBASESIZE (sizeof(LIBBASETYPE) + sizeof(struct Library *)*%d)\n"
290 , slist_length(cfg->rellibs)
294 if (cfg->rellibs) {
295 struct stringlist *sl;
296 int i, n = slist_length(cfg->rellibs);
298 for (sl=cfg->rellibs; sl; sl=sl->next, n--) {
299 fprintf(out,
300 "#ifndef AROS_RELLIB_OFFSET_%s\n"
301 "# error '%s' is not a relative library\n"
302 "#endif\n"
303 "const IPTR AROS_RELLIB_OFFSET_%s = LIBBASESIZE-sizeof(struct Library *)*%d;\n"
304 , upname(sl->s)
305 , sl->s
306 , upname(sl->s)
312 if (cfg->options & OPTION_DUPBASE) {
313 fprintf(
314 out,
315 "static LONG __GM_BaseSlot;\n"
316 "char *__aros_getoffsettable(void)\n"
317 "{\n"
318 " return (char *)GetTaskStorageSlot(__GM_BaseSlot);\n"
319 "}\n"
320 "void __aros_setoffsettable(void *base)\n"
321 "{\n"
322 " SetTaskStorageSlot(__GM_BaseSlot, (IPTR)base);\n"
323 "}\n"
324 "%s__aros_getbase_%s(void)\n"
325 "{\n"
326 " return (%s)__aros_getoffsettable();\n"
327 "}\n",
328 cfg->libbasetypeptrextern, cfg->libbase,
329 cfg->libbasetypeptrextern
331 } else if (cfg->rellibs || (cfg->options & OPTION_STACKCALL)) {
332 fprintf(out,
333 "#ifdef __aros_getoffsettable\n"
335 if ((cfg->options & OPTION_STACKCALL))
336 fprintf(out,
337 "#error Redefining __aros_setoffsettable is not permitted with stackcall APIs\n"
339 else
340 fprintf(out,
341 "#define __aros_getbase_%s() __aros_getoffsettable()\n",
342 cfg->libbase
344 fprintf(out,
345 "#else /* !__aros_getoffsettable */\n"
346 "static char *__GM_OffsetTable;\n"
347 "char *__aros_getoffsettable(void)\n"
348 "{\n"
349 " return __GM_OffsetTable;\n"
350 "}\n"
351 "BOOL __aros_setoffsettable(char *base)\n"
352 "{\n"
353 " __GM_OffsetTable = base;\n"
354 " return TRUE;\n"
355 "}\n"
356 "%s__aros_getbase_%s(void)\n"
357 "{\n"
358 " return (%s)__aros_getoffsettable();\n"
359 "}\n"
360 "#endif /* __aros_getoffsettable */\n"
361 "\n",
362 cfg->libbasetypeptrextern, cfg->libbase,
363 cfg->libbasetypeptrextern
367 if (cfg->rellibs)
369 struct stringlist *sl;
371 for (sl = cfg->rellibs; sl; sl = sl->next)
373 fprintf(out,
374 "AROS_IMPORT_ASM_SYM(void *,__GM_rellib_base_%s,AROS_RELLIB_BASE_%s);\n"
375 , sl->s
376 , upname(sl->s)
381 for (classlistit = cfg->classlist; classlistit != NULL; classlistit = classlistit->next)
383 /* For the main class basename is the same as the module basename */
384 if (strcmp(classlistit->basename, cfg->basename) == 0)
386 if (classlistit->classptr_var == NULL)
388 fprintf(out,
389 "#if !defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
390 "static APTR GM_UNIQUENAME(%sClass);\n"
391 "#define GM_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
392 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
393 "#define %s_STORE_CLASSPTR 1\n"
394 "#elif defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
395 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_CLASSPTR_FIELD(LIBBASE))\n"
396 "#elif !defined(GM_CLASSPTR_FIELD) && defined(%s_CLASSPTR_FIELD)\n"
397 "#define GM_CLASSPTR_FIELD(LIBBASE) (%s_CLASSPTR_FIELD(LIBBASE))\n"
398 "#endif\n",
399 classlistit->basename,
400 classlistit->basename,
401 classlistit->basename,
402 classlistit->basename, classlistit->basename,
403 classlistit->basename,
404 classlistit->basename,
405 classlistit->basename,
406 classlistit->basename,
407 classlistit->basename
410 else
412 fprintf(out,
413 "#define GM_CLASSPTR_FIELD(LIBBASE) (%s)\n"
414 "#define %s_CLASSPTR_FIELD(LIBBASE) (%s)\n"
415 "#define %s_STORE_CLASSPTR 1\n",
416 classlistit->classptr_var,
417 classlistit->basename, classlistit->classptr_var,
418 classlistit->basename
422 else
424 if (classlistit->classptr_var == NULL)
426 fprintf(out,
427 "#if !defined(%s_CLASSPTR_FIELD)\n"
428 "static APTR GM_UNIQUENAME(%sClass);\n"
429 "#define %s_CLASSPTR_FIELD(LIBBASE) (GM_UNIQUENAME(%sClass))\n"
430 "#define %s_STORE_CLASSPTR 1\n"
431 "#endif\n",
432 classlistit->basename,
433 classlistit->basename,
434 classlistit->basename, classlistit->basename,
435 classlistit->basename
438 else
440 fprintf(out,
441 "#define %s_CLASSPTR_FIELD(LIBBASE) (%s)\n"
442 "#define %s_STORE_CLASSPTR 1\n",
443 classlistit->basename, classlistit->classptr_var,
444 classlistit->basename
450 /* Write out the defines for the functions of the function table */
451 writefuncdefs(out, cfg, cfg->funclist);
452 /* Write internal stubs */
453 writefuncinternalstubs(out, cfg, cfg->funclist);
454 fprintf(out, "\n");
457 /* Write out the includes needed for the classes */
458 if (cfg->classlist != NULL)
459 writeboopsiincludes(out);
461 for (classlistit = cfg->classlist; classlistit != NULL; classlistit = classlistit->next)
463 switch (classlistit->classtype)
465 case MUI:
466 case MCC:
467 case MCP:
468 if (!muiinc)
470 writemuiincludes(out);
471 muiinc = 1;
473 /* Fall through: also write boopsi includes */
474 case GADGET:
475 case DATATYPE:
476 case CLASS:
477 case IMAGE:
478 if (!boopsiinc)
480 writeboopsiincludes(out);
481 boopsiinc = 1;
483 break;
484 case HIDD:
485 if (!oopinc)
487 writeoopincludes(out);
488 oopinc = 1;
490 break;
491 default:
492 fprintf(stderr, "Internal error: unhandled classtype in writedecl\n");
493 exit(20);
499 static void writedeclsets(FILE *out, struct config *cfg)
501 /* PROGRAM_ENTRIES is marked as handled but are just ignored in modules */
502 fprintf(out,
503 "THIS_PROGRAM_HANDLES_SYMBOLSET(INIT)\n"
504 "THIS_PROGRAM_HANDLES_SYMBOLSET(EXIT)\n"
505 "DECLARESET(INIT)\n"
506 "DECLARESET(EXIT)\n"
507 "THIS_PROGRAM_HANDLES_SYMBOLSET(PROGRAM_ENTRIES)\n"
508 "DECLARESET(PROGRAM_ENTRIES)\n"
510 if (cfg->modtype != HANDLER)
511 fprintf(out,
512 "THIS_PROGRAM_HANDLES_SYMBOLSET(CTORS)\n"
513 "THIS_PROGRAM_HANDLES_SYMBOLSET(DTORS)\n"
514 "DECLARESET(CTORS)\n"
515 "DECLARESET(DTORS)\n"
516 "THIS_PROGRAM_HANDLES_SYMBOLSET(INITLIB)\n"
517 "THIS_PROGRAM_HANDLES_SYMBOLSET(EXPUNGELIB)\n"
518 "DECLARESET(INITLIB)\n"
519 "DECLARESET(EXPUNGELIB)\n"
521 if (!(cfg->options & OPTION_NOAUTOLIB))
523 fprintf(out,
524 "THIS_PROGRAM_HANDLES_SYMBOLSET(LIBS)\n"
525 "DECLARESET(LIBS)\n"
527 if (cfg->rellibs)
528 fprintf(out,
529 "THIS_PROGRAM_HANDLES_SYMBOLSET(RELLIBS)\n"
530 "DECLARESET(RELLIBS)\n"
533 if (!(cfg->options & OPTION_NOOPENCLOSE))
534 fprintf(out,
535 "THIS_PROGRAM_HANDLES_SYMBOLSET(OPENLIB)\n"
536 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLOSELIB)\n"
537 "DECLARESET(OPENLIB)\n"
538 "DECLARESET(CLOSELIB)\n"
540 if (cfg->modtype == DEVICE)
541 fprintf(out,
542 "THIS_PROGRAM_HANDLES_SYMBOLSET(OPENDEV)\n"
543 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLOSEDEV)\n"
544 "DECLARESET(OPENDEV)\n"
545 "DECLARESET(CLOSEDEV)\n"
547 if (cfg->classlist != NULL)
548 fprintf(out,
549 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLASSESINIT)\n"
550 "THIS_PROGRAM_HANDLES_SYMBOLSET(CLASSESEXPUNGE)\n"
551 "DECLARESET(CLASSESINIT)\n"
552 "DECLARESET(CLASSESEXPUNGE)\n"
553 "#define ADD2INITCLASSES(symbol, pri) ADD2SET(symbol, CLASSESINIT, pri)\n"
554 "#define ADD2EXPUNGECLASSES(symbol, pri) ADD2SET(symbol, CLASSESEXPUNGE, pri)\n"
556 fprintf(out, "\n");
560 static void writeresident(FILE *out, struct config *cfg)
562 char *rt_skip = cfg->addromtag;
564 if (rt_skip)
565 fprintf(out, "extern const struct Resident %s;\n", rt_skip);
566 else
568 rt_skip = "GM_UNIQUENAME(End)";
569 fprintf(out, "extern const int %s;\n", rt_skip);
571 fprintf(out,
572 "extern const APTR GM_UNIQUENAME(FuncTable)[];\n"
574 if (cfg->options & OPTION_RESAUTOINIT)
575 fprintf(out, "static const struct InitTable GM_UNIQUENAME(InitTable);\n");
576 fprintf(out,
577 "\n"
578 "extern const char GM_UNIQUENAME(LibName)[];\n"
579 "extern const char GM_UNIQUENAME(LibID)[];\n"
580 "extern const char GM_UNIQUENAME(Copyright)[];\n"
581 "\n"
584 if (cfg->options & OPTION_RESAUTOINIT)
586 fprintf(out,
587 "#define __freebase(LIBBASE)\\\n"
588 "do {\\\n"
589 " UWORD negsize, possize;\\\n"
590 " UBYTE *negptr = (UBYTE *)LIBBASE;\\\n"
591 " negsize = ((struct Library *)LIBBASE)->lib_NegSize;\\\n"
592 " negptr -= negsize;\\\n"
593 " possize = ((struct Library *)LIBBASE)->lib_PosSize;\\\n"
594 " FreeMem (negptr, negsize+possize);\\\n"
595 "} while(0)\n"
596 "\n");
599 fprintf(out,
600 "AROS_UFP3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
601 " AROS_UFPA(LIBBASETYPEPTR, LIBBASE, D0),\n"
602 " AROS_UFPA(BPTR, segList, A0),\n"
603 " AROS_UFPA(struct ExecBase *, sysBase, A6)\n"
604 ");\n"
606 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
608 fprintf(out,
609 "AROS_LD1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
610 " AROS_LDA(LIBBASETYPEPTR, extralh, D0),\n"
611 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
612 ");\n"
613 "\n",
614 cfg->basename
617 fprintf(out,
618 "struct Resident const GM_UNIQUENAME(ROMTag) =\n"
619 "{\n"
620 " RTC_MATCHWORD,\n"
621 " (struct Resident *)&GM_UNIQUENAME(ROMTag),\n"
622 " (APTR)&%s,\n"
623 " RESIDENTFLAGS,\n"
624 " VERSION_NUMBER,\n",
625 rt_skip
627 switch (cfg->modtype)
629 case LIBRARY:
630 case MUI:
631 case MCC:
632 case MCP:
633 case GADGET:
634 case DATATYPE:
635 case USBCLASS:
636 case HIDD:
637 fprintf(out, " NT_LIBRARY,\n");
638 break;
639 case DEVICE:
640 fprintf(out, " NT_DEVICE,\n");
641 break;
642 case RESOURCE:
643 case HANDLER:
644 fprintf(out, " NT_RESOURCE,\n");
645 break;
646 default:
647 fprintf(stderr, "Internal error: unsupported modtype for NT_...\n");
648 exit(20);
649 break;
651 fprintf(out,
652 " RESIDENTPRI,\n"
653 " (CONST_STRPTR)&GM_UNIQUENAME(LibName)[0],\n"
654 " (CONST_STRPTR)&GM_UNIQUENAME(LibID)[6],\n"
656 if (cfg->options & OPTION_RESAUTOINIT)
658 fprintf(out,
659 " (APTR)&GM_UNIQUENAME(InitTable)\n"
660 "};\n"
661 "\n"
662 "static struct InitTable\n"
663 "{\n"
664 " IPTR Size;\n"
665 " const APTR *FuncTable;\n"
666 " struct DataTable *DataTable;\n"
667 " APTR InitLibTable;\n"
668 "}\n"
669 "const GM_UNIQUENAME(InitTable) =\n"
670 "{\n"
671 " LIBBASESIZE,\n"
672 " &GM_UNIQUENAME(FuncTable)[0],\n"
673 " NULL,\n"
674 " (APTR)GM_UNIQUENAME(InitLib)\n"
675 "};\n"
678 else
679 fprintf(out, " (APTR)GM_UNIQUENAME(InitLib)\n};\n");
681 fprintf(out,
682 "\n"
683 "const char GM_UNIQUENAME(LibName)[] = MOD_NAME_STRING;\n"
684 "const char GM_UNIQUENAME(LibID)[] = VERSION_STRING;\n"
685 "const char GM_UNIQUENAME(Copyright)[] = COPYRIGHT_STRING;\n"
686 "\n"
690 static void writehandler(FILE *out, struct config *cfg)
692 int i, handlers=0;
693 struct handlerinfo *hl;
694 int need_fse = 0, need_dos = 0;
696 fprintf(out,
697 "\n"
698 "#include <resources/filesysres.h>\n"
699 "#include <aros/system.h>\n"
700 "#include <proto/arossupport.h>\n"
701 "#include <proto/expansion.h>\n"
702 "\n"
705 for (hl = cfg->handlerlist; hl != NULL; hl = hl->next) {
706 if (hl->type == HANDLER_DOSNODE)
707 need_dos = 1;
708 else
709 need_fse = 1;
710 handlers++;
713 fprintf(out,
714 "\n"
715 "LONG %s(struct ExecBase *sysBase);\n"
716 "extern const LONG const __aros_libreq_SysBase __attribute__((weak));\n"
717 "\n"
718 "__startup AROS_PROCH(GM_UNIQUENAME(Handler), argptr, argsize, SysBase)\n"
719 "{\n"
720 " AROS_PROCFUNC_INIT\n"
721 "\n"
722 " LONG ret = RETURN_FAIL;\n"
723 "\n"
724 " if (!SysBase || SysBase->LibNode.lib_Version < __aros_libreq_SysBase)\n"
725 " return ERROR_INVALID_RESIDENT_LIBRARY;\n"
726 " if (set_call_funcs(SETNAME(INIT), 1, 1)) {\n"
727 " ret = %s(SysBase);\n"
728 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
729 " }\n"
730 "\n"
731 " return ret;\n"
732 "\n"
733 " AROS_PROCFUNC_EXIT\n"
734 "}\n"
735 , cfg->handlerfunc
736 , cfg->handlerfunc
739 fprintf(out,
740 "\n"
741 "static inline BOOL GM_UNIQUENAME(InitHandler)(struct ExecBase *SysBase)\n"
742 "{\n"
745 if (!need_dos && !need_fse) {
746 fprintf(out,
747 " return TRUE;\n"
748 "}\n"
750 return;
753 fprintf(out,
754 " BPTR seg;\n"
757 if (need_dos) {
758 fprintf(out,
759 " struct Library *ExpansionBase;\n"
762 if (need_fse) {
763 fprintf(out,
764 " struct FileSysResource *fsr;\n"
765 " struct FileSysEntry *fse;\n"
768 if (need_fse) {
769 fprintf(out,
770 " fsr = (struct FileSysResource *)OpenResource(\"FileSystem.resource\");\n"
771 " if (fsr == NULL)\n"
772 " return FALSE;\n"
775 if (need_dos) {
776 fprintf(out,
777 " ExpansionBase = OpenLibrary(\"expansion.library\", 36);\n"
778 " if (ExpansionBase == NULL)\n"
779 " return FALSE;\n"
782 fprintf(out,
783 " seg = CreateSegList(GM_UNIQUENAME(Handler));\n"
784 " if (seg != BNULL) {\n"
786 for (hl = cfg->handlerlist; hl != NULL; hl = hl->next)
788 switch (hl->type)
790 case HANDLER_DOSNODE:
791 fprintf(out,
792 "\n"
793 " {\n"
794 " struct DeviceNode *node;\n"
795 " IPTR pp[] = { \n"
796 " (IPTR)\"%s\",\n"
797 " (IPTR)NULL,\n"
798 " (IPTR)0,\n"
799 " (IPTR)0,\n"
800 " (IPTR)0\n"
801 " };\n"
802 " node = MakeDosNode((APTR)pp);\n"
803 " if (node) {\n"
804 " node->dn_StackSize = %u;\n"
805 " node->dn_SegList = seg;\n"
806 " node->dn_Startup = (BPTR)%d;\n"
807 " node->dn_Priority = %d;\n"
808 " node->dn_GlobalVec = (BPTR)(SIPTR)-1;\n"
809 " AddBootNode(%d, 0, node, NULL);\n"
810 " }\n"
811 " }\n"
812 "\n"
813 , hl->name
814 , hl->stacksize
815 , hl->startup
816 , hl->priority
817 , hl->bootpri
819 break;
820 case HANDLER_RESIDENT:
821 case HANDLER_DOSTYPE:
822 fprintf(out,
823 "\n"
824 " /* Check to see if we can allocate the memory for the fse */\n"
825 " fse = AllocMem(sizeof(*fse), MEMF_CLEAR);\n"
826 " if (fse) {\n"
827 " fse->fse_Node.ln_Name = VERSION_STRING;\n"
828 " fse->fse_Node.ln_Pri = %d;\n"
829 " fse->fse_DosType = 0x%08x;\n"
830 " fse->fse_Version = (MAJOR_VERSION << 16) | MINOR_VERSION;\n"
831 " fse->fse_PatchFlags = FSEF_SEGLIST | FSEF_GLOBALVEC | FSEF_PRIORITY;\n"
832 , hl->autodetect
833 , hl->id
835 if (hl->stacksize)
837 fprintf(out,
838 " fse->fse_PatchFlags |= FSEF_STACKSIZE;\n"
839 " fse->fse_StackSize = %d;\n"
840 , hl->stacksize
843 if (hl->name)
844 fprintf(out,
845 " fse->fse_PatchFlags |= FSEF_HANDLER;\n"
846 " fse->fse_Handler = AROS_CONST_BSTR(\"%s\");\n"
847 , hl->name);
848 fprintf(out,
849 " fse->fse_Priority = %d;\n"
850 " fse->fse_SegList = seg;\n"
851 " fse->fse_GlobalVec = (BPTR)(SIPTR)-1;\n"
852 " fse->fse_Startup = (BPTR)%d;\n"
853 "\n"
854 " /* Add to the list. I know forbid and permit are\n"
855 " * a little unnecessary for the pre-multitasking state\n"
856 " * we should be in at this point, but you never know\n"
857 " * who's going to blindly copy this code as an example.\n"
858 " */\n"
859 " Forbid();\n"
860 " Enqueue(&fsr->fsr_FileSysEntries, (struct Node *)fse);\n"
861 " Permit();\n"
862 " }\n"
863 , hl->priority
864 , hl->startup
866 break;
869 fprintf(out,
870 " }\n"
872 if (need_dos) {
873 fprintf(out,
874 " CloseLibrary(ExpansionBase);\n"
877 fprintf(out,
878 " return TRUE;\n"
879 "}\n"
880 "\n"
884 static void writeinitlib(FILE *out, struct config *cfg)
886 if (cfg->handlerlist)
887 writehandler(out, cfg);
889 fprintf(out,
890 "extern const LONG const __aros_libreq_SysBase __attribute__((weak));\n"
891 "\n"
892 "AROS_UFH3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
893 " AROS_UFHA(LIBBASETYPEPTR, LIBBASE, D0),\n"
894 " AROS_UFHA(BPTR, segList, A0),\n"
895 " AROS_UFHA(struct ExecBase *, sysBase, A6)\n"
896 ")\n"
897 "{\n"
898 " AROS_USERFUNC_INIT\n"
901 if (cfg->modtype == HANDLER) {
902 fprintf(out,
903 "\n"
904 " GM_UNIQUENAME(InitHandler)(sysBase);\n"
905 " return LIBBASE;\n"
906 "\n"
907 " AROS_USERFUNC_EXIT\n"
908 "}\n"
909 "\n"
911 return;
914 fprintf(out,
915 "\n"
916 " int ok;\n"
917 " int initcalled = 0;\n"
919 /* Set the global SysBase, needed for __aros_setoffsettable()/__aros_getoffsettable() */
920 if (cfg->options & OPTION_DUPBASE)
921 fprintf(out,
922 " SysBase = sysBase;\n"
924 else
925 fprintf(out,
926 " struct ExecBase *SysBase = sysBase;\n"
928 fprintf(out,
929 "\n"
930 "#ifdef GM_SYSBASE_FIELD\n"
931 " GM_SYSBASE_FIELD(LIBBASE) = (APTR)SysBase;\n"
932 "#endif\n"
933 " if (!SysBase || SysBase->LibNode.lib_Version < __aros_libreq_SysBase)\n"
934 " return NULL;\n"
935 "\n"
938 if (cfg->options & OPTION_RESAUTOINIT) {
939 fprintf(out,
940 "#ifdef GM_OOPBASE_FIELD\n"
941 " GM_OOPBASE_FIELD(LIBBASE) = OpenLibrary(\"oop.library\",0);\n"
942 " if (GM_OOPBASE_FIELD(LIBBASE) == NULL)\n"
943 " return NULL;\n"
944 "#endif\n"
948 if (!(cfg->options & OPTION_RESAUTOINIT))
950 fprintf(out,
951 " int vecsize;\n"
952 " struct Node *n;\n"
953 " char *mem;\n"
954 "\n"
955 " vecsize = FUNCTIONS_COUNT * LIB_VECTSIZE;\n"
956 " if (vecsize > 0)\n"
957 " vecsize = ((vecsize-1)/sizeof(IPTR) + 1)*sizeof(IPTR);\n"
958 " mem = AllocMem(vecsize+sizeof(LIBBASETYPE), MEMF_PUBLIC|MEMF_CLEAR);\n"
959 " if (mem == NULL)\n"
960 " return NULL;\n"
961 " LIBBASE = (LIBBASETYPEPTR)(mem + vecsize);\n"
962 " n = (struct Node *)LIBBASE;\n"
963 " n->ln_Type = NT_RESOURCE;\n"
964 " n->ln_Pri = RESIDENTPRI;\n"
965 " n->ln_Name = (char *)GM_UNIQUENAME(LibName);\n"
966 " MakeFunctions(LIBBASE, (APTR)GM_UNIQUENAME(FuncTable), NULL);\n"
968 if ((cfg->modtype != RESOURCE) && (cfg->options & OPTION_SELFINIT))
970 fprintf(out,
971 " ((struct Library*)LIBBASE)->lib_NegSize = vecsize;\n"
972 " ((struct Library*)LIBBASE)->lib_PosSize = sizeof(LIBBASETYPE);\n"
977 else
979 fprintf(out,
980 " ((struct Library *)LIBBASE)->lib_Revision = REVISION_NUMBER;\n"
984 if (cfg->options & OPTION_DUPBASE)
985 fprintf(out,
986 " __GM_BaseSlot = AllocTaskStorageSlot();\n"
987 " if (!SetTaskStorageSlot(__GM_BaseSlot, (IPTR)LIBBASE)) {\n"
988 " FreeTaskStorageSlot(__GM_BaseSlot);\n"
989 " return NULL;\n"
990 " }\n"
992 else if (cfg->rellibs || (cfg->options & OPTION_STACKCALL))
993 fprintf(out,
994 " __aros_setoffsettable((char *)LIBBASE);\n"
996 if (cfg->options & OPTION_PERTASKBASE)
997 fprintf(out,
998 " __pertaskslot = AllocTaskStorageSlot();\n"
1001 if (!(cfg->options & OPTION_NOEXPUNGE) && cfg->modtype!=RESOURCE)
1002 fprintf(out, " GM_SEGLIST_FIELD(LIBBASE) = segList;\n");
1003 if (cfg->options & OPTION_DUPBASE)
1004 fprintf(out, " GM_ROOTBASE_FIELD(LIBBASE) = (LIBBASETYPEPTR)LIBBASE;\n");
1005 fprintf(out, " if (");
1006 if (!(cfg->options & OPTION_NOAUTOLIB))
1007 fprintf(out, "set_open_libraries() && ");
1008 if (cfg->rellibs)
1009 fprintf(out, "set_open_rellibraries(LIBBASE) && ");
1010 fprintf(out,
1011 "set_call_funcs(SETNAME(INIT), 1, 1) &&"
1013 if (cfg->classlist != NULL)
1014 fprintf(out, "set_call_libfuncs(SETNAME(CLASSESINIT), 1, 1, LIBBASE) && ");
1015 fprintf(out,
1016 "1)\n"
1017 " {\n"
1018 " set_call_funcs(SETNAME(CTORS), -1, 0);\n"
1019 "\n"
1022 fprintf(out,
1023 " initcalled = 1;\n"
1024 " ok = set_call_libfuncs(SETNAME(INITLIB), 1, 1, LIBBASE);\n"
1025 " }\n"
1026 " else\n"
1027 " ok = 0;\n"
1028 "\n"
1029 " if (!ok)\n"
1030 " {\n"
1031 " if (initcalled)\n"
1032 " set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 0, LIBBASE);\n"
1033 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
1034 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
1036 if (cfg->classlist != NULL)
1037 fprintf(out, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, LIBBASE);\n");
1038 if (cfg->rellibs)
1039 fprintf(out, " set_close_rellibraries(LIBBASE);\n");
1040 if (!(cfg->options & OPTION_NOAUTOLIB))
1041 fprintf(out, " set_close_libraries();\n");
1043 if (cfg->options & OPTION_RESAUTOINIT)
1045 fprintf(out,
1046 "\n"
1047 " __freebase(LIBBASE);\n"
1050 else
1052 fprintf(out,
1053 "\n"
1054 " FreeMem(mem, vecsize+LIBBASESIZE);\n"
1057 fprintf(out,
1058 " return NULL;\n"
1059 " }\n"
1060 " else\n"
1061 " {\n"
1064 if (!(cfg->options & OPTION_RESAUTOINIT) && !(cfg->options & OPTION_SELFINIT))
1066 switch (cfg->modtype)
1068 case RESOURCE:
1069 fprintf(out, " AddResource(LIBBASE);\n");
1070 break;
1072 case DEVICE:
1073 fprintf(out, " AddDevice(LIBBASE);\n");
1075 default:
1076 /* Everything else is library */
1077 fprintf(out, " AddLibrary(LIBBASE);\n");
1078 break;
1082 fprintf(out,
1083 " return LIBBASE;\n"
1084 " }\n"
1085 "\n"
1086 " AROS_USERFUNC_EXIT\n"
1087 "}\n"
1088 "\n"
1092 static void writeopenlib(FILE *out, struct config *cfg)
1094 switch (cfg->modtype)
1096 case RESOURCE:
1097 fprintf(stderr, "Internal error: writeopenlib called for a resource\n");
1098 break;
1099 case HANDLER:
1100 fprintf(stderr, "Internal error: writeopenlib called for a handler\n");
1101 break;
1102 case DEVICE:
1103 if (cfg->options & OPTION_NOOPENCLOSE)
1104 fprintf(out,
1105 "AROS_LD3 (void, GM_UNIQUENAME(OpenLib),\n"
1106 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1107 " AROS_LDA(ULONG, unitnum, D0),\n"
1108 " AROS_LDA(ULONG, flags, D1),\n"
1109 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1110 ");\n",
1111 cfg->basename
1113 else
1115 fprintf(out,
1116 "AROS_LH3 (void, GM_UNIQUENAME(OpenLib),\n"
1117 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1118 " AROS_LHA(IPTR, unitnum, D0),\n"
1119 " AROS_LHA(ULONG, flags, D1),\n"
1120 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1121 ")\n",
1122 cfg->basename
1124 fprintf(out,
1125 "{\n"
1126 " AROS_LIBFUNC_INIT\n"
1127 "\n"
1128 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, LIBBASE)\n"
1129 " && set_call_devfuncs(SETNAME(OPENDEV), 1, 1, LIBBASE, ioreq, unitnum, flags)\n"
1130 " )\n"
1131 " {\n"
1132 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1133 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1134 "\n"
1135 " ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;\n"
1136 " }\n"
1137 " else\n"
1138 " {\n"
1139 " if (ioreq->io_Error >= 0)\n"
1140 " ioreq->io_Error = IOERR_OPENFAIL;\n"
1141 " }\n"
1142 "\n"
1143 " return;\n"
1144 "\n"
1145 " AROS_LIBFUNC_EXIT\n"
1146 "}\n"
1147 "\n"
1150 break;
1151 default:
1152 if (cfg->options & OPTION_NOOPENCLOSE)
1154 fprintf(out,
1155 "AROS_LD1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
1156 " AROS_LDA (ULONG, version, D0),\n"
1157 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1158 ");\n",
1159 cfg->basename
1161 return;
1163 fprintf(out,
1164 "AROS_LH1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
1165 " AROS_LHA (ULONG, version, D0),\n"
1166 " LIBBASETYPEPTR, LIBBASE, 1, %s\n"
1167 ")\n"
1168 "{\n"
1169 " AROS_LIBFUNC_INIT\n"
1170 "\n",
1171 cfg->basename
1173 if (!(cfg->options & OPTION_DUPBASE))
1175 fprintf(out,
1176 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, LIBBASE) )\n"
1177 " {\n"
1178 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1179 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1180 " return LIBBASE;\n"
1181 " }\n"
1182 "\n"
1183 " return NULL;\n"
1184 "\n"
1185 " AROS_LIBFUNC_EXIT\n"
1186 "}\n"
1187 "\n"
1190 else /* OPTION_DUPBASE */
1192 fprintf(out,
1193 " struct Library *newlib = NULL;\n"
1194 " UWORD possize = ((struct Library *)LIBBASE)->lib_PosSize;\n"
1195 " LIBBASETYPEPTR oldbase = (LIBBASETYPEPTR)__aros_getbase_%s();\n",
1196 cfg->libbase
1198 if (cfg->options & OPTION_PERTASKBASE)
1199 fprintf(out,
1200 " struct Task *thistask = FindTask(NULL);\n"
1201 " LIBBASETYPEPTR oldpertaskbase = __GM_GetPerTaskBase();\n"
1202 " newlib = (struct Library *)oldpertaskbase;\n"
1203 " if (newlib)\n"
1204 " {\n"
1205 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1206 " if (dupbase->task != thistask)\n"
1207 " newlib = NULL;\n"
1208 " else if (thistask->tc_Node.ln_Type == NT_PROCESS\n"
1209 " && dupbase->retaddr != ((struct Process *)thistask)->pr_ReturnAddr\n"
1210 " )\n"
1211 " newlib = NULL;\n"
1212 " else\n"
1213 " dupbase->taskopencount++;\n"
1214 " }\n"
1217 fprintf(out,
1218 "\n"
1219 " if (newlib == NULL)\n"
1220 " {\n"
1221 " newlib = MakeLibrary(GM_UNIQUENAME(InitTable).FuncTable,\n"
1222 " GM_UNIQUENAME(InitTable).DataTable,\n"
1223 " NULL,\n"
1224 " GM_UNIQUENAME(InitTable).Size,\n"
1225 " (BPTR)NULL\n"
1226 " );\n"
1227 " if (newlib == NULL)\n"
1228 " return NULL;\n"
1229 "\n"
1230 " CopyMem(LIBBASE, newlib, possize);\n"
1231 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1232 " dupbase->oldbase = oldbase;\n"
1233 " __aros_setoffsettable((char *)newlib);\n"
1235 if (cfg->options & OPTION_PERTASKBASE)
1236 fprintf(out,
1237 " dupbase->task = thistask;\n"
1238 " if (thistask->tc_Node.ln_Type == NT_PROCESS)\n"
1239 " dupbase->retaddr = ((struct Process *)thistask)->pr_ReturnAddr;\n"
1240 " dupbase->oldpertaskbase = oldpertaskbase;\n"
1241 " dupbase->taskopencount = 1;\n"
1242 " __GM_SetPerTaskBase((LIBBASETYPEPTR)newlib);\n"
1244 fprintf(out,
1245 "\n"
1246 " if (!(set_open_rellibraries(newlib)\n"
1247 " && set_call_libfuncs(SETNAME(OPENLIB), 1, 1, newlib)\n"
1248 " )\n"
1249 " )\n"
1250 " {\n");
1251 if (cfg->options & OPTION_PERTASKBASE)
1252 fprintf(out,
1253 " __GM_SetPerTaskBase(oldpertaskbase);\n");
1254 fprintf(out,
1255 " __freebase(newlib);\n"
1256 " return NULL;\n"
1257 " }\n"
1258 "\n"
1259 " ((struct Library *)LIBBASE)->lib_OpenCnt++;\n"
1260 " ((struct Library *)LIBBASE)->lib_Flags &= ~LIBF_DELEXP;\n"
1261 " }\n"
1262 "\n"
1263 " return (LIBBASETYPEPTR)newlib;\n"
1264 "\n"
1265 " AROS_LIBFUNC_EXIT\n"
1266 "}\n"
1267 "\n"
1274 static void writecloselib(FILE *out, struct config *cfg)
1276 if (cfg->options & OPTION_NOOPENCLOSE)
1278 if (cfg->modtype != DEVICE)
1279 fprintf(out,
1280 "AROS_LD0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1281 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1282 ");\n",
1283 cfg->basename
1285 else
1286 fprintf(out,
1287 "AROS_LD1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1288 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1289 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1290 ");\n",
1291 cfg->basename
1293 return;
1295 if (cfg->modtype != DEVICE)
1296 fprintf(out,
1297 "AROS_LH0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1298 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1299 ")\n",
1300 cfg->basename
1302 else
1303 fprintf(out,
1304 "AROS_LH1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1305 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1306 " LIBBASETYPEPTR, LIBBASE, 2, %s\n"
1307 ")\n",
1308 cfg->basename
1311 fprintf(out,
1312 "{\n"
1313 " AROS_LIBFUNC_INIT\n"
1314 "\n"
1316 if (cfg->modtype == DEVICE)
1317 fprintf(out,
1318 " if (!set_call_devfuncs(SETNAME(CLOSEDEV), -1, 1, LIBBASE, ioreq, 0, 0))\n"
1319 " {\n"
1320 " return BNULL;\n"
1321 " }\n"
1323 if (!(cfg->options & OPTION_DUPBASE))
1325 fprintf(out,
1326 " ((struct Library *)LIBBASE)->lib_OpenCnt--;\n"
1327 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, LIBBASE);\n"
1330 else /* OPTION_DUPBASE */
1332 fprintf(out,
1333 " LIBBASETYPEPTR rootbase = GM_ROOTBASE_FIELD(LIBBASE);\n"
1334 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)LIBBASE;\n"
1336 if (cfg->options & OPTION_PERTASKBASE)
1337 fprintf(out,
1338 " dupbase->taskopencount--;\n"
1339 " if (dupbase->taskopencount != 0)\n"
1340 " return BNULL;\n"
1342 fprintf(out,
1343 "\n"
1344 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, LIBBASE);\n"
1345 " set_close_rellibraries(LIBBASE);\n"
1346 " __aros_setoffsettable((char *)dupbase->oldbase);\n"
1348 if (cfg->options & OPTION_PERTASKBASE)
1349 fprintf(out,
1350 " __GM_SetPerTaskBase(((struct __GM_DupBase *)LIBBASE)->oldpertaskbase);\n"
1352 fprintf(out,
1353 " __freebase(LIBBASE);\n"
1354 " LIBBASE = rootbase;\n"
1355 " ((struct Library *)LIBBASE)->lib_OpenCnt--;\n"
1356 "\n"
1359 if (!(cfg->options & OPTION_NOEXPUNGE))
1360 fprintf(out,
1361 " if\n"
1362 " (\n"
1363 " (((struct Library *)LIBBASE)->lib_OpenCnt == 0)\n"
1364 " && (((struct Library *)LIBBASE)->lib_Flags & LIBF_DELEXP)\n"
1365 " )\n"
1366 " {\n"
1367 " return AROS_LC1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1368 " AROS_LCA(LIBBASETYPEPTR, LIBBASE, D0),\n"
1369 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
1370 " );\n"
1371 " }\n",
1372 cfg->basename
1374 fprintf(out,
1375 "\n"
1376 " return BNULL;\n"
1377 "\n"
1378 " AROS_LIBFUNC_EXIT\n"
1379 "}\n"
1380 "\n"
1385 static void writeexpungelib(FILE *out, struct config *cfg)
1387 fprintf(out,
1388 "AROS_LH1 (BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1389 " AROS_LHA(LIBBASETYPEPTR, extralh, D0),\n"
1390 " LIBBASETYPEPTR, LIBBASE, 3, %s\n"
1391 ")\n",
1392 cfg->basename
1394 fprintf(out,
1395 "{\n"
1396 " AROS_LIBFUNC_INIT\n"
1397 "\n"
1399 if (!(cfg->options & OPTION_NOEXPUNGE))
1401 if (cfg->options & OPTION_RESAUTOINIT) {
1402 fprintf(out,
1403 "#ifdef GM_SYSBASE_FIELD\n"
1404 " struct ExecBase *SysBase = (struct ExecBase *)GM_SYSBASE_FIELD(LIBBASE);\n"
1405 "#endif\n"
1408 fprintf(out,
1409 "\n"
1410 " if ( ((struct Library *)LIBBASE)->lib_OpenCnt == 0 )\n"
1411 " {\n"
1412 " BPTR seglist = GM_SEGLIST_FIELD(LIBBASE);\n"
1413 "\n"
1414 " if(!set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 1, LIBBASE))\n"
1415 " {\n"
1416 " ((struct Library *)LIBBASE)->lib_Flags |= LIBF_DELEXP;\n"
1417 " return BNULL;\n"
1418 " }\n"
1419 "\n"
1420 " Remove((struct Node *)LIBBASE);\n"
1421 "\n"
1422 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
1423 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
1425 if (cfg->classlist != NULL)
1426 fprintf(out, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, LIBBASE);\n");
1427 if (cfg->rellibs)
1428 fprintf(out, " set_close_rellibraries(LIBBASE);\n");
1429 if (!(cfg->options & OPTION_NOAUTOLIB))
1430 fprintf(out, " set_close_libraries();\n"
1431 "#ifdef GM_OOPBASE_FIELD\n"
1432 " CloseLibrary((struct Library *)GM_OOPBASE_FIELD(LIBBASE));\n"
1433 "#endif\n"
1435 if (cfg->options & OPTION_PERTASKBASE)
1436 fprintf(out,
1437 " FreeTaskStorageSlot(__pertaskslot);\n"
1438 " __pertaskslot = 0;\n"
1440 fprintf(out,
1441 "\n"
1442 " __freebase(LIBBASE);\n"
1443 "\n"
1444 " return seglist;\n"
1445 " }\n"
1446 "\n"
1447 " ((struct Library *)LIBBASE)->lib_Flags |= LIBF_DELEXP;\n"
1450 fprintf(out,
1451 "\n"
1452 " return BNULL;\n"
1453 "\n"
1454 " AROS_LIBFUNC_EXIT\n"
1455 "}\n"
1456 "\n"
1461 static void writeextfunclib(FILE *out, struct config *cfg)
1463 fprintf(out,
1464 "AROS_LH0 (LIBBASETYPEPTR, GM_UNIQUENAME(ExtFuncLib),\n"
1465 " LIBBASETYPEPTR, LIBBASE, 4, %s\n"
1466 ")\n"
1467 "{\n"
1468 " AROS_LIBFUNC_INIT\n"
1469 " return NULL;\n"
1470 " AROS_LIBFUNC_EXIT\n"
1471 "}\n"
1472 "\n",
1473 cfg->basename
1478 static void
1479 writefunctable(FILE *out,
1480 struct config *cfg
1483 struct functionhead *funclistit = cfg->funclist;
1484 struct functionarg *arglistit;
1485 unsigned int lvo;
1486 int i;
1487 char *name, *type;
1488 int lastversion = 0;
1490 /* lvo contains the number of functions already printed in the functable */
1491 lvo = 0;
1493 if (!(cfg->options & OPTION_NORESIDENT))
1495 fprintf(out,
1496 "\n"
1497 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1498 "{\n"
1500 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
1502 fprintf(out,
1503 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(OpenLib),%s,1),\n"
1504 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(CloseLib),%s,2),\n"
1505 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExpungeLib),%s,3),\n"
1506 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExtFuncLib),%s,4),\n",
1507 cfg->basename, cfg->basename, cfg->basename, cfg->basename
1509 lvo += 4;
1511 if (cfg->modtype == MCC || cfg->modtype == MUI || cfg->modtype == MCP)
1513 lvo++;
1514 fprintf(out,
1515 " &AROS_SLIB_ENTRY(MCC_Query,%s,%d),\n",
1516 cfg->basename, lvo
1519 else if (cfg->modtype == DATATYPE)
1521 lvo++;
1522 fprintf(out,
1523 " &AROS_SLIB_ENTRY(ObtainEngine,%s,%d),\n",
1524 cfg->basename, lvo
1528 else /* NORESIDENT */
1530 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
1532 int neednull = 0;
1533 struct functionhead *funclistit2;
1535 if (funclistit->lvo != 1)
1537 fprintf(stderr, "Module without a generated resident structure has to provide the Open function (LVO==1)\n");
1538 exit(20);
1540 else
1541 funclistit = funclistit->next;
1543 if (funclistit->lvo != 2)
1545 fprintf(stderr, "Module without a generated resident structure has to provide the Close function (LVO==2)\n");
1546 exit(20);
1548 else
1549 funclistit = funclistit->next;
1551 if (funclistit->lvo == 3)
1552 funclistit = funclistit->next;
1553 else
1554 neednull = 1;
1556 if (funclistit->lvo == 4)
1557 funclistit = funclistit->next;
1558 else
1559 neednull = 1;
1561 if (neednull)
1562 fprintf(out,
1563 "\n"
1564 "AROS_UFH1S(int, %s_null,\n"
1565 " AROS_UFHA(struct Library *, libbase, A6)\n"
1566 ")\n"
1567 "{\n"
1568 " AROS_USERFUNC_INIT\n"
1569 " return 0;\n"
1570 " AROS_USERFUNC_EXIT\n"
1571 "}\n",
1572 cfg->modulename
1575 funclistit = cfg->funclist;
1576 funclistit2 = funclistit->next;
1577 fprintf(out,
1578 "\n"
1579 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1580 "{\n"
1581 " &AROS_SLIB_ENTRY(%s,%s,%d),\n"
1582 " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1583 funclistit->internalname, cfg->basename, lvo+1,
1584 funclistit2->internalname, cfg->basename, lvo+2
1586 lvo += 2;
1587 funclistit = funclistit2->next;
1589 if (funclistit->lvo == 3)
1591 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1592 funclistit->internalname, cfg->basename, lvo+1
1594 funclistit = funclistit->next;
1596 else
1597 fprintf(out, " &%s_null,\n", cfg->modulename);
1598 lvo++;
1600 if (funclistit->lvo == 4)
1602 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1603 funclistit->internalname, cfg->basename, lvo+1
1605 funclistit = funclistit->next;
1607 else
1608 fprintf(out, " &%s_null,\n", cfg->modulename);
1609 lvo++;
1611 else
1613 fprintf(out,
1614 "\n"
1615 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1616 "{\n");
1620 while (funclistit != NULL)
1622 for (i = lvo+1; i<funclistit->lvo; i++)
1623 fprintf(out, " NULL,\n");
1624 lvo = funclistit->lvo;
1626 switch (funclistit->libcall)
1628 case STACK:
1629 case REGISTER:
1630 case REGISTERMACRO:
1631 if (funclistit->version != lastversion) {
1632 lastversion = funclistit->version;
1633 fprintf(out, " /* Version %d */\n", lastversion);
1635 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n", funclistit->internalname, cfg->basename, lvo);
1636 break;
1638 default:
1639 fprintf(stderr, "Internal error: unhandled libcall type in writestart\n");
1640 exit(20);
1641 break;
1644 funclistit = funclistit->next;
1647 fprintf(out, " (void *)-1\n};\n");
1651 static void writesets(FILE *out, struct config *cfg)
1653 fprintf(out,
1654 "DEFINESET(INIT)\n"
1655 "DEFINESET(EXIT)\n"
1657 if (cfg->modtype != HANDLER)
1658 fprintf(out,
1659 "DEFINESET(CTORS)\n"
1660 "DEFINESET(DTORS)\n"
1661 "DEFINESET(INITLIB)\n"
1662 "DEFINESET(EXPUNGELIB)\n"
1664 if (!(cfg->options & OPTION_NOOPENCLOSE))
1665 fprintf(out,
1666 "DEFINESET(OPENLIB)\n"
1667 "DEFINESET(CLOSELIB)\n"
1669 if (cfg->modtype == DEVICE)
1670 fprintf(out,
1671 "DEFINESET(OPENDEV)\n"
1672 "DEFINESET(CLOSEDEV)\n"
1674 if (cfg->classlist != NULL)
1675 fprintf(out,
1676 "DEFINESET(CLASSESINIT)\n"
1677 "DEFINESET(CLASSESEXPUNGE)\n"
1679 fprintf(out, "\n");