nforce.device: Use AROS_UFIx() macros
[AROS.git] / tools / genmodule / writestart.c
blob15bdafdc7b24bf592845949906a38b22ee106cfe
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 /* Some general info on the function of the generated code and how they work
27 for .library modules (TODO: add docs for other module types):
29 The code in this file will write out the inittable, the function table,
30 the InitLib, OpenLib, CloseLib and ExpungeLib function.
31 InitLib will call the functions in the ADD2INIT symbolset.
32 OpenLib will call the functions in the ADD2OPENLIB symbolset.
33 CloseLib will call the functions in the ADD2CLOSELIB symbolset.
34 ExpungeLib will call the fucntions in the ADD2EXIT symbolset.
36 Currently 3 types of libraries are supported: 1 libbase, a per-opener
37 libbase and a per-task libbase.
38 * For 1 libbase the libbase is initialized once in InitLib and
39 then returned for each call to OpenLib. OpenLib and CloseLib keep track
40 of the times the libraries is still open; if it is 0 the library may be
41 expunged.
42 * The per-opener libbase will create a new libbase for each call to OpenLib
43 After InitLib has called the ADD2INIT functions the fields in the root
44 libbase may have been initialized to a certain value. These value are
45 copied in the newly generated libbase and then the ADD2OPENLIB functions
46 are called with the new libbase.
47 A per-opener libbase is indicated by the OPTION_DUPBASE flag in cfg->options.
48 Currently, a task memory slot is used to store the libbase when a function
49 of the library is entered. With proper support from the compiler this could
50 be changed to use a reserved register - probably increasing speed. This
51 could be implemented later on without breaking backwards compatibility.
52 Special provision has been taken to restore the state of the memory slot
53 after CloseLib to what it was when OpenLib is called. This is to handle the
54 case properly where the library is used both in the parent and child
55 of a Task run with RunCommand().
56 * The per-task libbase will create a new libbase for a call to OpenLib when
57 there does not exist a libbase yet for this task. This is handled by reserving
58 an additional task memory slot. In OpenLib the contents of this memory slot
59 is checked and only a new libbase will be generated when the libbase stored
60 there is not for the current Task. Also on then the ADD2OPENLIB
61 A separate counter is added to count the number of times the libbase is opened
62 in the same task. The libbase will also only be closed and removed if this
63 counter reaches 0 and only then the ADD2CLOSELIB functions are called.
64 A per-task libbase is indicated by both flags OPTION_DUPBASE and
65 OPTION_PERTASKBASE in cfg->options.
66 It was decided to use an extra slot for storing the per-task libbase to check
67 in OpenLib if a new libbase has to created. This is to increase flexibility
68 during calling of the library functions. If the library supports this the
69 library can still be called with another libbase then the libbase stored in the
70 per-task slot, or the library function can be called from another task then the
71 one that opened the libbase.
72 Also here special provision has been taken to restore the state of the memory
73 slot after CloseLib to what it was when OpenLib is called.
75 void writestart(struct config *cfg)
77 FILE *out;
78 char line[256], *banner;
79 struct classinfo *cl;
81 snprintf(line, 255, "%s/%s_start.c", cfg->gendir, cfg->modulename);
82 out = fopen(line, "w");
84 if (out == NULL)
86 perror(line);
87 exit(20);
90 banner = getBanner(cfg);
91 fprintf(out, "%s", banner);
92 freeBanner(banner);
94 fprintf(out,
95 "/* For comments and explanation of generated code look in writestart.c source code\n"
96 " of the genmodule program */\n"
99 writedecl(out, cfg);
100 if (!(cfg->options & OPTION_NORESIDENT))
102 writeresident(out, cfg);
103 writedeclsets(out, cfg);
104 writeinitlib(out, cfg);
105 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
107 writeopenlib(out, cfg);
108 writecloselib(out, cfg);
109 writeexpungelib(out, cfg);
110 writeextfunclib(out, cfg);
111 if (cfg->modtype == MCC || cfg->modtype == MUI || cfg->modtype == MCP)
112 writemccquery(out, cfg);
113 else if (cfg->modtype == DATATYPE)
114 writeobtainengine(out, cfg);
116 writesets(out, cfg);
119 if (cfg->modtype != HANDLER)
120 writefunctable(out, cfg);
122 for (cl = cfg->classlist; cl != NULL; cl = cl->next)
124 switch (cl->classtype)
126 case MCC:
127 case MUI:
128 case MCP:
129 /* Second argument to next call: the class is not the main class if it is not
130 * the first class or the modtype is not a MUI class
132 writemccinit(out, cl != cfg->classlist || cfg->modtype != cl->classtype, cl);
133 break;
134 case GADGET:
135 case DATATYPE:
136 case CLASS:
137 case IMAGE:
138 writeclassinit(out, cl);
139 break;
140 case HIDD:
141 writeoopinit(out, cl);
142 break;
143 default:
144 fprintf(stdout, "Internal error: unsupported classtype in writestart\n");
145 exit(20);
149 fclose(out);
153 static void writedecl(FILE *out, struct config *cfg)
155 struct stringlist *linelistit;
156 int boopsiinc=0, muiinc=0, oopinc=0;
157 struct functionhead *funclistit;
158 struct functionarg *arglistit;
159 struct classinfo *classlistit;
160 char *type, *name;
162 if (cfg->modtype == DEVICE)
164 fprintf(out,
165 "#include <exec/io.h>\n"
166 "#include <exec/errors.h>\n"
169 fprintf(out,
170 "#include <exec/types.h>\n"
171 "#include <exec/libraries.h>\n"
172 "#include <exec/resident.h>\n"
173 "#include <aros/libcall.h>\n"
174 "#include <aros/asmcall.h>\n"
175 "#include <aros/symbolsets.h>\n"
176 "#include <dos/dos.h>\n"
177 "\n"
178 "#include \"%s_libdefs.h\"\n"
179 "\n"
180 "#ifdef SysBase\n"
181 "#undef SysBase\n"
182 "#endif\n"
183 "\n"
184 "#include <proto/exec.h>\n"
185 "#include <proto/alib.h>\n"
186 "#ifndef __AROS__\n"
187 "struct ExecBase *SysBase = NULL;\n"
188 "#endif\n"
189 "\n",
190 cfg->modulename
193 /* Write out declaration section provided in the config file */
194 for (linelistit = cfg->cdeflines; linelistit != NULL; linelistit = linelistit->next)
196 fprintf(out, "%s\n", linelistit->s);
199 /* Is there a variable for storing the segList ? */
200 if (!(cfg->options & OPTION_NOEXPUNGE) && cfg->modtype!=RESOURCE && cfg->modtype != HANDLER)
202 fprintf(out,
203 "#ifndef GM_SEGLIST_FIELD\n"
204 "static BPTR __attribute__((unused)) GM_UNIQUENAME(seglist);\n"
205 "#define GM_SEGLIST_FIELD(lh) (GM_UNIQUENAME(seglist))\n"
206 "#endif\n"
209 if (cfg->options & OPTION_DUPBASE)
211 fprintf(out,
212 "#ifndef GM_ROOTBASE_FIELD\n"
213 "static LIBBASETYPEPTR GM_UNIQUENAME(rootbase);\n"
214 "#define GM_ROOTBASE_FIELD(lh) (GM_UNIQUENAME(rootbase))\n"
215 "#endif\n"
216 "LONG __GM_BaseSlot;\n"
217 /* If AROS_GM_GETBASE is defined, then it is a
218 * macro that generates the __GM_GetBase() function
219 * in assembly. See include/aros/x86_64/cpu.h for
220 * an example implementation.
222 "#ifdef AROS_GM_GETBASE\n"
223 "extern void *__GM_GetBase(void);\n"
224 "AROS_GM_GETBASE()\n"
225 "static inline void *__GM_GetBase_Safe(void)\n"
226 "{\n"
227 " return (LIBBASETYPEPTR)GetTaskStorageSlot(__GM_BaseSlot);\n"
228 "}\n"
229 "#else\n"
230 "void *__GM_GetBase(void)\n"
231 "{\n"
232 " return (void *)GetTaskStorageSlot(__GM_BaseSlot);\n"
233 "}\n"
234 "#define __GM_GetBase_Safe() __GM_GetBase()\n"
235 "#endif\n"
236 "static inline BOOL __GM_SetBase_Safe(LIBBASETYPEPTR base)\n"
237 "{\n"
238 " return SetTaskStorageSlot(__GM_BaseSlot, (IPTR)base);\n"
239 "}\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 if (cfg->relbases)
255 fprintf(out,
256 " struct Library *relbase[%d];\n"
257 , slist_length(cfg->relbases)
260 fprintf(out,
261 "};\n"
262 "#define LIBBASESIZE sizeof(struct __GM_DupBase)\n"
264 if (cfg->relbases)
266 struct stringlist *sl;
267 int i;
269 for (sl=cfg->relbases, i = 0; sl; sl=sl->next, i++) {
270 fprintf(out,
271 "const IPTR %s_offset = offsetof(struct __GM_DupBase, relbase[%d]);\n"
272 , sl->s
277 if (cfg->options & OPTION_PERTASKBASE)
279 fprintf(out,
280 "static LONG __pertaskslot;\n"
281 "LIBBASETYPEPTR __GM_GetBaseParent(LIBBASETYPEPTR base)\n"
282 "{\n"
283 " return ((struct __GM_DupBase *)base)->oldpertaskbase;\n"
284 "}\n"
285 "static inline LIBBASETYPEPTR __GM_GetPerTaskBase(void)\n"
286 "{\n"
287 " return (LIBBASETYPEPTR)GetTaskStorageSlot(__pertaskslot);\n"
288 "}\n"
289 "static inline void __GM_SetPerTaskBase(LIBBASETYPEPTR base)\n"
290 "{\n"
291 " SetTaskStorageSlot(__pertaskslot, (IPTR)base);\n"
292 "}\n"
295 if (cfg->relbases)
297 struct stringlist *sl;
299 for (sl = cfg->relbases; sl; sl = sl->next)
301 fprintf(out,
302 "AROS_IMPORT_ASM_SYM(void *,__%s,__aros_rellib_%s);\n"
303 , sl->s
304 , sl->s
309 else
310 fprintf(out, "#define LIBBASESIZE sizeof(LIBBASETYPE)\n");
312 for (classlistit = cfg->classlist; classlistit != NULL; classlistit = classlistit->next)
314 /* For the main class basename is the same as the module basename */
315 if (strcmp(classlistit->basename, cfg->basename) == 0)
317 if (classlistit->classptr_var == NULL)
319 fprintf(out,
320 "#if !defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
321 "static APTR GM_UNIQUENAME(%sClass);\n"
322 "#define GM_CLASSPTR_FIELD(lh) (GM_UNIQUENAME(%sClass))\n"
323 "#define %s_CLASSPTR_FIELD(lh) (GM_UNIQUENAME(%sClass))\n"
324 "#define %s_STORE_CLASSPTR 1\n"
325 "#elif defined(GM_CLASSPTR_FIELD) && !defined(%s_CLASSPTR_FIELD)\n"
326 "#define %s_CLASSPTR_FIELD(lh) (GM_CLASSPTR_FIELD(lh))\n"
327 "#elif !defined(GM_CLASSPTR_FIELD) && defined(%s_CLASSPTR_FIELD)\n"
328 "#define GM_CLASSPTR_FIELD(lh) (%s_CLASSPTR_FIELD(lh))\n"
329 "#endif\n",
330 classlistit->basename,
331 classlistit->basename,
332 classlistit->basename,
333 classlistit->basename, classlistit->basename,
334 classlistit->basename,
335 classlistit->basename,
336 classlistit->basename,
337 classlistit->basename,
338 classlistit->basename
341 else
343 fprintf(out,
344 "#define GM_CLASSPTR_FIELD(lh) (%s)\n"
345 "#define %s_CLASSPTR_FIELD(lh) (%s)\n"
346 "#define %s_STORE_CLASSPTR 1\n",
347 classlistit->classptr_var,
348 classlistit->basename, classlistit->classptr_var,
349 classlistit->basename
353 else
355 if (classlistit->classptr_var == NULL)
357 fprintf(out,
358 "#if !defined(%s_CLASSPTR_FIELD)\n"
359 "static APTR GM_UNIQUENAME(%sClass);\n"
360 "#define %s_CLASSPTR_FIELD(lh) (GM_UNIQUENAME(%sClass))\n"
361 "#define %s_STORE_CLASSPTR 1\n"
362 "#endif\n",
363 classlistit->basename,
364 classlistit->basename,
365 classlistit->basename, classlistit->basename,
366 classlistit->basename
369 else
371 fprintf(out,
372 "#define %s_CLASSPTR_FIELD(lh) (%s)\n"
373 "#define %s_STORE_CLASSPTR 1\n",
374 classlistit->basename, classlistit->classptr_var,
375 classlistit->basename
381 /* Write out the defines for the functions of the function table */
382 writefuncdefs(out, cfg, cfg->funclist);
383 fprintf(out, "\n");
386 /* Write out the includes needed for the classes */
387 if (cfg->classlist != NULL)
388 writeboopsiincludes(out);
390 for (classlistit = cfg->classlist; classlistit != NULL; classlistit = classlistit->next)
392 switch (classlistit->classtype)
394 case MUI:
395 case MCC:
396 case MCP:
397 if (!muiinc)
399 writemuiincludes(out);
400 muiinc = 1;
402 /* Fall through: also write boopsi includes */
403 case GADGET:
404 case DATATYPE:
405 case CLASS:
406 case IMAGE:
407 if (!boopsiinc)
409 writeboopsiincludes(out);
410 boopsiinc = 1;
412 break;
413 case HIDD:
414 if (!oopinc)
416 writeoopincludes(out);
417 oopinc = 1;
419 break;
420 default:
421 fprintf(stderr, "Internal error: unhandled classtype in writedecl\n");
422 exit(20);
428 static void writedeclsets(FILE *out, struct config *cfg)
430 fprintf(out,
431 "THIS_PROGRAM_HANDLES_SYMBOLSETS\n"
432 "DECLARESET(INIT)\n"
433 "DECLARESET(EXIT)\n"
434 "DECLARESET(CTORS)\n"
435 "DECLARESET(DTORS)\n"
436 "DECLARESET(INITLIB)\n"
437 "DECLARESET(EXPUNGELIB)\n"
439 if (!(cfg->options & OPTION_NOOPENCLOSE))
440 fprintf(out,
441 "DECLARESET(OPENLIB)\n"
442 "DECLARESET(CLOSELIB)\n"
444 if (cfg->modtype == DEVICE)
445 fprintf(out,
446 "DECLARESET(OPENDEV)\n"
447 "DECLARESET(CLOSEDEV)\n"
449 if (cfg->classlist != NULL)
450 fprintf(out,
451 "DECLARESET(CLASSESINIT)\n"
452 "DECLARESET(CLASSESEXPUNGE)\n"
453 "#define ADD2INITCLASSES(symbol, pri) ADD2SET(symbol, classesinit, pri)\n"
454 "#define ADD2EXPUNGECLASSES(symbol, pri) ADD2SET(symbol, classesexpunge, pri)\n"
456 fprintf(out, "\n");
460 static void writeresident(FILE *out, struct config *cfg)
462 char *rt_skip = cfg->addromtag;
464 if (rt_skip)
465 fprintf(out, "extern const struct Resident %s;\n", rt_skip);
466 else
468 rt_skip = "GM_UNIQUENAME(End)";
469 fprintf(out, "extern const int %s;\n", rt_skip);
471 fprintf(out,
472 "extern const APTR GM_UNIQUENAME(FuncTable)[];\n"
474 if (cfg->options & OPTION_RESAUTOINIT)
475 fprintf(out, "static const struct InitTable GM_UNIQUENAME(InitTable);\n");
476 fprintf(out,
477 "\n"
478 "extern const char GM_UNIQUENAME(LibName)[];\n"
479 "extern const char GM_UNIQUENAME(LibID)[];\n"
480 "extern const char GM_UNIQUENAME(Copyright)[];\n"
481 "\n"
484 if (cfg->options & OPTION_RESAUTOINIT)
486 fprintf(out,
487 "#define __freebase(lh)\\\n"
488 "do {\\\n"
489 " UWORD negsize, possize;\\\n"
490 " UBYTE *negptr = (UBYTE *)lh;\\\n"
491 " negsize = ((struct Library *)lh)->lib_NegSize;\\\n"
492 " negptr -= negsize;\\\n"
493 " possize = ((struct Library *)lh)->lib_PosSize;\\\n"
494 " FreeMem (negptr, negsize+possize);\\\n"
495 "} while(0)\n"
496 "\n");
499 fprintf(out,
500 "AROS_UFP3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
501 " AROS_UFPA(LIBBASETYPEPTR, lh, D0),\n"
502 " AROS_UFPA(BPTR, segList, A0),\n"
503 " AROS_UFPA(struct ExecBase *, sysBase, A6)\n"
504 ");\n"
506 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
508 fprintf(out,
509 "AROS_LD1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
510 " AROS_LDA(LIBBASETYPEPTR, extralh, D0),\n"
511 " LIBBASETYPEPTR, lh, 3, %s\n"
512 ");\n"
513 "\n",
514 cfg->basename
517 fprintf(out,
518 "struct Resident const GM_UNIQUENAME(ROMTag) =\n"
519 "{\n"
520 " RTC_MATCHWORD,\n"
521 " (struct Resident *)&GM_UNIQUENAME(ROMTag),\n"
522 " (APTR)&%s,\n"
523 " RESIDENTFLAGS,\n"
524 " VERSION_NUMBER,\n",
525 rt_skip
527 switch (cfg->modtype)
529 case LIBRARY:
530 case MUI:
531 case MCC:
532 case MCP:
533 case GADGET:
534 case DATATYPE:
535 case USBCLASS:
536 case HIDD:
537 fprintf(out, " NT_LIBRARY,\n");
538 break;
539 case DEVICE:
540 fprintf(out, " NT_DEVICE,\n");
541 break;
542 case RESOURCE:
543 case HANDLER:
544 fprintf(out, " NT_RESOURCE,\n");
545 break;
546 default:
547 fprintf(stderr, "Internal error: unsupported modtype for NT_...\n");
548 exit(20);
549 break;
551 fprintf(out,
552 " RESIDENTPRI,\n"
553 " (CONST_STRPTR)&GM_UNIQUENAME(LibName)[0],\n"
554 " (CONST_STRPTR)&GM_UNIQUENAME(LibID)[6],\n"
556 if (cfg->options & OPTION_RESAUTOINIT)
558 fprintf(out,
559 " (APTR)&GM_UNIQUENAME(InitTable)\n"
560 "};\n"
561 "\n"
562 "static struct InitTable\n"
563 "{\n"
564 " IPTR Size;\n"
565 " const APTR *FuncTable;\n"
566 " struct DataTable *DataTable;\n"
567 " APTR InitLibTable;\n"
568 "}\n"
569 "const GM_UNIQUENAME(InitTable) =\n"
570 "{\n"
571 " LIBBASESIZE,\n"
572 " &GM_UNIQUENAME(FuncTable)[0],\n"
573 " NULL,\n"
574 " (APTR)GM_UNIQUENAME(InitLib)\n"
575 "};\n"
578 else
579 fprintf(out, " (APTR)GM_UNIQUENAME(InitLib)\n};\n");
581 fprintf(out,
582 "\n"
583 "const char GM_UNIQUENAME(LibName)[] = MOD_NAME_STRING;\n"
584 "const char GM_UNIQUENAME(LibID)[] = VERSION_STRING;\n"
585 "const char GM_UNIQUENAME(Copyright)[] = COPYRIGHT_STRING;\n"
586 "\n"
590 static void writehandler(FILE *out, struct config *cfg)
592 int i;
593 struct handlerinfo *hl;
595 fprintf(out,
596 "\n"
597 "#include <resources/filesysres.h>\n"
598 "#include <aros/system.h>\n"
599 "#include <proto/arossupport.h>\n"
600 "#include <proto/dos.h>\n"
601 "\n"
604 for (hl = cfg->handlerlist; hl != NULL; hl = hl->next) {
605 fprintf(out,
606 "extern void %s(void);\n",
607 hl->handler);
610 fprintf(out,
611 "\n"
612 "void GM_UNIQUENAME(InitHandler)(void)\n"
613 "{\n"
614 " struct FileSysResource *fsr;\n"
615 " int i;\n"
616 " const struct {\n"
617 " ULONG id;\n"
618 " BSTR name;\n"
619 " BYTE autodetect;\n"
620 " BYTE priority;\n"
621 " ULONG stacksize;\n"
622 " void (*handler)(void);\n"
623 " } const __handler[] = { \n");
624 for (hl = cfg->handlerlist; hl != NULL; hl = hl->next)
626 switch (hl->type)
628 case HANDLER_RESIDENT:
629 fprintf(out,
630 " { .id = 0, .name = AROS_CONST_BSTR(\"%s\"), .handler = %s }, \n",
631 hl->name, hl->handler);
632 break;
633 case HANDLER_DOSTYPE:
634 fprintf(out,
635 " { .id = 0x%08x, .name = AROS_CONST_BSTR(MOD_NAME_STRING), .handler = %s, .autodetect = %d, .priority = %d, .stacksize = %d*sizeof(IPTR) }, \n",
636 hl->id, hl->handler, hl->autodetect, hl->priority, hl->stacksize);
637 break;
640 fprintf(out,
641 " };\n"
642 " BPTR seg[sizeof(__handler)/sizeof(__handler[0])] = { };\n"
643 "\n"
644 " fsr = (struct FileSysResource *)OpenResource(\"FileSystem.resource\");\n"
645 " if (fsr == NULL)\n"
646 " return;\n"
647 "\n"
648 " for (i = 0; i < sizeof(__handler)/sizeof(__handler[0]); i++) {\n"
649 " struct FileSysEntry *fse;\n"
650 " int j;\n"
651 "\n"
652 " /* Check to see if we can allocate the memory for the fse */\n"
653 " fse = AllocMem(sizeof(*fse), MEMF_CLEAR);\n"
654 " if (!fse)\n"
655 " return;\n"
656 "\n"
657 " /* Did we already make a segment for this handler? */\n"
658 " for (j = 0; j < i; j++)\n"
659 " if (__handler[i].handler == __handler[j].handler)\n"
660 " break;\n"
661 " if (seg[j] == (BPTR)0)\n"
662 " seg[j] = CreateSegList(__handler[j].handler);\n"
663 " if (seg[j] == BNULL) {\n"
664 " FreeMem(fse, sizeof(*fse));\n"
665 " return;\n"
666 " }\n"
667 " \n"
668 " /* DOS ID based handlers\n"
669 " * NOTE: fse_DosType == 0 is a special flag use in\n"
670 " * dos.library's init to add the handler to the\n"
671 " * resident segment list\n"
672 " */\n"
673 " fse->fse_Node.ln_Name = VERSION_STRING;\n"
674 " fse->fse_Node.ln_Pri = __handler[i].autodetect;\n"
675 " fse->fse_DosType = __handler[i].id;\n"
676 " fse->fse_Version = (MAJOR_VERSION << 16) | MINOR_VERSION;\n"
677 " fse->fse_PatchFlags = FSEF_SEGLIST | FSEF_GLOBALVEC | FSEF_HANDLER | FSEF_PRIORITY;\n"
678 " if (__handler[i].stacksize) {\n"
679 " fse->fse_PatchFlags |= FSEF_STACKSIZE;\n"
680 " fse->fse_StackSize = __handler[i].stacksize;\n"
681 " }\n"
682 " fse->fse_Handler = __handler[i].name;\n"
683 " fse->fse_Priority = __handler[i].priority;\n"
684 " fse->fse_SegList = seg[j];\n"
685 " fse->fse_GlobalVec = (BPTR)(SIPTR)-1;\n"
686 " \n"
687 " /* Add to the list. I know forbid and permit are\n"
688 " * a little unnecessary for the pre-multitasking state\n"
689 " * we should be in at this point, but you never know\n"
690 " * who's going to blindly copy this code as an example.\n"
691 " */\n"
692 " Forbid();\n"
693 " Enqueue(&fsr->fsr_FileSysEntries, (struct Node *)fse);\n"
694 " Permit();\n"
695 " }\n"
696 "}\n");
699 static void writeinitlib(FILE *out, struct config *cfg)
701 if (cfg->handlerlist)
702 writehandler(out, cfg);
704 fprintf(out,
705 "AROS_UFH3 (LIBBASETYPEPTR, GM_UNIQUENAME(InitLib),\n"
706 " AROS_UFHA(LIBBASETYPEPTR, lh, D0),\n"
707 " AROS_UFHA(BPTR, segList, A0),\n"
708 " AROS_UFHA(struct ExecBase *, sysBase, A6)\n"
709 ")\n"
710 "{\n"
711 " AROS_USERFUNC_INIT\n"
712 "\n"
713 " int ok;\n"
715 if (cfg->modtype != HANDLER)
716 fprintf(out,
717 " int initcalled = 0;\n"
719 fprintf(out,
720 "\n"
723 if (cfg->options & OPTION_RESAUTOINIT) {
724 fprintf(out,
725 "#ifndef __AROS__\n"
726 " SysBase = sysBase;\n"
727 "#endif\n"
728 "#ifdef GM_SYSBASE_FIELD\n"
729 " GM_SYSBASE_FIELD(lh) = (APTR)sysBase;\n"
730 "#endif\n"
731 "#ifdef GM_OOPBASE_FIELD\n"
732 " GM_OOPBASE_FIELD(lh) = OpenLibrary(\"oop.library\",0);\n"
733 " if (GM_OOPBASE_FIELD(lh) == NULL)\n"
734 " return NULL;\n"
735 "#endif\n"
739 if (cfg->modtype != HANDLER)
741 if (!(cfg->options & OPTION_RESAUTOINIT))
743 fprintf(out,
744 " int vecsize;\n"
745 " struct Node *n;\n"
746 " char *mem;\n"
747 "\n"
748 " vecsize = FUNCTIONS_COUNT * LIB_VECTSIZE;\n"
749 " if (vecsize > 0)\n"
750 " vecsize = ((vecsize-1)/sizeof(IPTR) + 1)*sizeof(IPTR);\n"
751 " mem = AllocMem(vecsize+sizeof(LIBBASETYPE), MEMF_PUBLIC|MEMF_CLEAR);\n"
752 " if (mem == NULL)\n"
753 " return NULL;\n"
754 " lh = (LIBBASETYPEPTR)(mem + vecsize);\n"
755 " n = (struct Node *)lh;\n"
756 " n->ln_Type = NT_RESOURCE;\n"
757 " n->ln_Pri = RESIDENTPRI;\n"
758 " n->ln_Name = (char *)GM_UNIQUENAME(LibName);\n"
759 " MakeFunctions(lh, (APTR)GM_UNIQUENAME(FuncTable), NULL);\n"
761 if ((cfg->modtype != RESOURCE) && (cfg->options & OPTION_SELFINIT))
763 fprintf(out,
764 " ((struct Library*)lh)->lib_NegSize = vecsize;\n"
765 " ((struct Library*)lh)->lib_PosSize = sizeof(LIBBASETYPE);\n"
770 else
772 fprintf(out,
773 " ((struct Library *)lh)->lib_Revision = REVISION_NUMBER;\n"
778 if (cfg->options & OPTION_DUPBASE)
779 fprintf(out,
780 " __GM_BaseSlot = AllocTaskStorageSlot();\n"
781 " if (!__GM_SetBase_Safe(lh)) {\n"
782 " FreeTaskStorageSlot(__GM_BaseSlot);\n"
783 " return NULL;\n"
784 " }\n"
786 if (cfg->options & OPTION_PERTASKBASE)
787 fprintf(out,
788 " __pertaskslot = AllocTaskStorageSlot();\n"
791 if (!(cfg->options & OPTION_NOEXPUNGE) && cfg->modtype!=RESOURCE && cfg->modtype != HANDLER)
792 fprintf(out, " GM_SEGLIST_FIELD(lh) = segList;\n");
793 if (cfg->options & OPTION_DUPBASE)
794 fprintf(out, " GM_ROOTBASE_FIELD(lh) = (LIBBASETYPEPTR)lh;\n");
795 fprintf(out, " if (");
796 if (!(cfg->options & OPTION_NOAUTOLIB))
797 fprintf(out, "set_open_libraries() && ");
798 if (cfg->classlist != NULL)
799 fprintf(out, "set_call_libfuncs(SETNAME(CLASSESINIT), 1, 1, lh) && ");
800 fprintf(out,
801 "set_call_funcs(SETNAME(INIT), 1, 1) )\n"
802 " {\n"
803 " set_call_funcs(SETNAME(CTORS), -1, 0);\n"
804 "\n"
807 if (cfg->modtype == HANDLER)
808 fprintf(out,
809 " ok = 1;\n");
810 else
811 fprintf(out,
812 " initcalled = 1;\n"
813 " ok = set_call_libfuncs(SETNAME(INITLIB), 1, 1, lh);\n");
814 fprintf(out,
815 " }\n"
816 " else\n"
817 " ok = 0;\n"
818 "\n"
819 " if (!ok)\n"
820 " {\n"
823 if (cfg->modtype != HANDLER)
824 fprintf(out,
825 " if (initcalled)\n"
826 " set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 0, lh);\n");
828 fprintf(out,
829 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
830 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
832 if (cfg->classlist != NULL)
833 fprintf(out, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, lh);\n");
834 if (!(cfg->options & OPTION_NOAUTOLIB))
835 fprintf(out, " set_close_libraries();\n");
837 if (cfg->modtype != HANDLER)
839 if (cfg->options & OPTION_RESAUTOINIT)
841 fprintf(out,
842 "\n"
843 " __freebase(lh);\n"
846 else
848 fprintf(out,
849 "\n"
850 " FreeMem(mem, vecsize+LIBBASESIZE);\n"
854 fprintf(out,
855 " return NULL;\n"
856 " }\n"
857 " else\n"
858 " {\n"
861 if (!(cfg->options & OPTION_RESAUTOINIT) && !(cfg->options & OPTION_SELFINIT))
863 switch (cfg->modtype)
865 case RESOURCE:
866 fprintf(out, " AddResource(lh);\n");
867 break;
869 case DEVICE:
870 fprintf(out, " AddDevice(lh);\n");
872 case HANDLER:
873 /* Bare handlers don't require adding at all */
874 break;
876 default:
877 /* Everything else is library */
878 fprintf(out, " AddLibrary(lh);\n");
879 break;
883 if (cfg->handlerlist)
884 fprintf(out, " GM_UNIQUENAME(InitHandler)();\n");
886 fprintf(out,
887 " return lh;\n"
888 " }\n"
889 "\n"
890 " AROS_USERFUNC_EXIT\n"
891 "}\n"
892 "\n"
896 static void writeopenlib(FILE *out, struct config *cfg)
898 switch (cfg->modtype)
900 case RESOURCE:
901 fprintf(stderr, "Internal error: writeopenlib called for a resource\n");
902 break;
903 case HANDLER:
904 fprintf(stderr, "Internal error: writeopenlib called for a handler\n");
905 break;
906 case DEVICE:
907 if (cfg->options & OPTION_NOOPENCLOSE)
908 fprintf(out,
909 "AROS_LD3 (void, GM_UNIQUENAME(OpenLib),\n"
910 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
911 " AROS_LDA(ULONG, unitnum, D0),\n"
912 " AROS_LDA(ULONG, flags, D1),\n"
913 " LIBBASETYPEPTR, lh, 1, %s\n"
914 ");\n",
915 cfg->basename
917 else
919 fprintf(out,
920 "AROS_LH3 (void, GM_UNIQUENAME(OpenLib),\n"
921 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
922 " AROS_LHA(IPTR, unitnum, D0),\n"
923 " AROS_LHA(ULONG, flags, D1),\n"
924 " LIBBASETYPEPTR, lh, 1, %s\n"
925 ")\n",
926 cfg->basename
928 fprintf(out,
929 "{\n"
930 " AROS_LIBFUNC_INIT\n"
931 "\n"
932 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, lh)\n"
933 " && set_call_devfuncs(SETNAME(OPENDEV), 1, 1, lh, ioreq, unitnum, flags)\n"
934 " )\n"
935 " {\n"
936 " ((struct Library *)lh)->lib_OpenCnt++;\n"
937 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
938 "\n"
939 " ioreq->io_Message.mn_Node.ln_Type = NT_REPLYMSG;\n"
940 " }\n"
941 " else\n"
942 " {\n"
943 " if (ioreq->io_Error >= 0)\n"
944 " ioreq->io_Error = IOERR_OPENFAIL;\n"
945 " }\n"
946 "\n"
947 " return;\n"
948 "\n"
949 " AROS_LIBFUNC_EXIT\n"
950 "}\n"
951 "\n"
954 break;
955 default:
956 if (cfg->options & OPTION_NOOPENCLOSE)
958 fprintf(out,
959 "AROS_LD1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
960 " AROS_LDA (ULONG, version, D0),\n"
961 " LIBBASETYPEPTR, lh, 1, %s\n"
962 ");\n",
963 cfg->basename
965 return;
967 fprintf(out,
968 "AROS_LH1 (LIBBASETYPEPTR, GM_UNIQUENAME(OpenLib),\n"
969 " AROS_LHA (ULONG, version, D0),\n"
970 " LIBBASETYPEPTR, lh, 1, %s\n"
971 ")\n"
972 "{\n"
973 " AROS_LIBFUNC_INIT\n"
974 "\n",
975 cfg->basename
977 if (!(cfg->options & OPTION_DUPBASE))
979 fprintf(out,
980 " if ( set_call_libfuncs(SETNAME(OPENLIB), 1, 1, lh) )\n"
981 " {\n"
982 " ((struct Library *)lh)->lib_OpenCnt++;\n"
983 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
984 "\n"
985 " return lh;\n"
986 " }\n"
987 "\n"
988 " return NULL;\n"
989 "\n"
990 " AROS_LIBFUNC_EXIT\n"
991 "}\n"
992 "\n"
995 else /* OPTION_DUPBASE */
997 fprintf(out,
998 " struct Library *newlib = NULL;\n"
999 " UWORD possize = ((struct Library *)lh)->lib_PosSize;\n"
1000 " LIBBASETYPEPTR oldbase = __GM_GetBase_Safe();\n"
1002 if (cfg->options & OPTION_PERTASKBASE)
1003 fprintf(out,
1004 " struct Task *thistask = FindTask(NULL);\n"
1005 " LIBBASETYPEPTR oldpertaskbase = __GM_GetPerTaskBase();\n"
1006 " newlib = (struct Library *)oldpertaskbase;\n"
1007 " if (newlib)\n"
1008 " {\n"
1009 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1010 " if (dupbase->task != thistask)\n"
1011 " newlib = NULL;\n"
1012 " else if (thistask->tc_Node.ln_Type == NT_PROCESS\n"
1013 " && dupbase->retaddr != ((struct Process *)thistask)->pr_ReturnAddr\n"
1014 " )\n"
1015 " newlib = NULL;\n"
1016 " else\n"
1017 " dupbase->taskopencount++;\n"
1018 " }\n"
1021 fprintf(out,
1022 "\n"
1023 " if (newlib == NULL)\n"
1024 " {\n"
1025 " newlib = MakeLibrary(GM_UNIQUENAME(InitTable).FuncTable,\n"
1026 " GM_UNIQUENAME(InitTable).DataTable,\n"
1027 " NULL,\n"
1028 " GM_UNIQUENAME(InitTable).Size,\n"
1029 " (BPTR)NULL\n"
1030 " );\n"
1031 " if (newlib == NULL)\n"
1032 " return NULL;\n"
1033 "\n"
1034 " CopyMem(lh, newlib, possize);\n"
1035 " __GM_SetBase_Safe((LIBBASETYPEPTR)newlib);\n"
1036 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)newlib;\n"
1037 " dupbase->oldbase = oldbase;\n"
1039 if (cfg->options & OPTION_PERTASKBASE)
1040 fprintf(out,
1041 " dupbase->task = thistask;\n"
1042 " if (thistask->tc_Node.ln_Type == NT_PROCESS)\n"
1043 " dupbase->retaddr = ((struct Process *)thistask)->pr_ReturnAddr;\n"
1044 " dupbase->oldpertaskbase = oldpertaskbase;\n"
1045 " dupbase->taskopencount = 1;\n"
1046 " __GM_SetPerTaskBase((LIBBASETYPEPTR)newlib);\n"
1048 fprintf(out,
1049 "\n"
1050 " if (!(set_open_rellibraries(newlib)\n"
1051 " && set_call_libfuncs(SETNAME(OPENLIB), 1, 1, newlib)\n"
1052 " )\n"
1053 " )\n"
1054 " {\n");
1055 if (cfg->options & OPTION_PERTASKBASE)
1056 fprintf(out,
1057 " __GM_SetPerTaskBase(oldpertaskbase);\n");
1058 fprintf(out,
1059 " __freebase(newlib);\n"
1060 " return NULL;\n"
1061 " }\n"
1062 "\n"
1063 " ((struct Library *)lh)->lib_OpenCnt++;\n"
1064 " ((struct Library *)lh)->lib_Flags &= ~LIBF_DELEXP;\n"
1065 " }\n"
1066 "\n"
1067 " return (LIBBASETYPEPTR)newlib;\n"
1068 "\n"
1069 " AROS_LIBFUNC_EXIT\n"
1070 "}\n"
1071 "\n"
1078 static void writecloselib(FILE *out, struct config *cfg)
1080 if (cfg->options & OPTION_NOOPENCLOSE)
1082 if (cfg->modtype != DEVICE)
1083 fprintf(out,
1084 "AROS_LD0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1085 " LIBBASETYPEPTR, lh, 2, %s\n"
1086 ");\n",
1087 cfg->basename
1089 else
1090 fprintf(out,
1091 "AROS_LD1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1092 " AROS_LDA(struct IORequest *, ioreq, A1),\n"
1093 " LIBBASETYPEPTR, lh, 2, %s\n"
1094 ");\n",
1095 cfg->basename
1097 return;
1099 if (cfg->modtype != DEVICE)
1100 fprintf(out,
1101 "AROS_LH0 (BPTR, GM_UNIQUENAME(CloseLib),\n"
1102 " LIBBASETYPEPTR, lh, 2, %s\n"
1103 ")\n",
1104 cfg->basename
1106 else
1107 fprintf(out,
1108 "AROS_LH1(BPTR, GM_UNIQUENAME(CloseLib),\n"
1109 " AROS_LHA(struct IORequest *, ioreq, A1),\n"
1110 " LIBBASETYPEPTR, lh, 2, %s\n"
1111 ")\n",
1112 cfg->basename
1115 fprintf(out,
1116 "{\n"
1117 " AROS_LIBFUNC_INIT\n"
1118 "\n"
1120 if (cfg->modtype == DEVICE)
1121 fprintf(out,
1122 " if (!set_call_devfuncs(SETNAME(CLOSEDEV), -1, 1, lh, ioreq, 0, 0))\n"
1123 " {\n"
1124 " return BNULL;\n"
1125 " }\n"
1127 if (!(cfg->options & OPTION_DUPBASE))
1129 fprintf(out,
1130 " ((struct Library *)lh)->lib_OpenCnt--;\n"
1131 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, lh);\n"
1134 else /* OPTION_DUPBASE */
1136 fprintf(out,
1137 " LIBBASETYPEPTR rootbase = GM_ROOTBASE_FIELD(lh);\n"
1138 " struct __GM_DupBase *dupbase = (struct __GM_DupBase *)lh;\n"
1140 if (cfg->options & OPTION_PERTASKBASE)
1141 fprintf(out,
1142 " dupbase->taskopencount--;\n"
1143 " if (dupbase->taskopencount != 0)\n"
1144 " return BNULL;\n"
1146 fprintf(out,
1147 "\n"
1148 " set_call_libfuncs(SETNAME(CLOSELIB), -1, 0, lh);\n"
1149 " set_close_rellibraries(lh);\n"
1150 " __GM_SetBase_Safe(dupbase->oldbase);\n"
1152 if (cfg->options & OPTION_PERTASKBASE)
1153 fprintf(out,
1154 " __GM_SetPerTaskBase(((struct __GM_DupBase *)lh)->oldpertaskbase);\n"
1156 fprintf(out,
1157 " __freebase(lh);\n"
1158 " lh = rootbase;\n"
1159 " ((struct Library *)lh)->lib_OpenCnt--;\n"
1160 "\n"
1163 if (!(cfg->options & OPTION_NOEXPUNGE))
1164 fprintf(out,
1165 " if\n"
1166 " (\n"
1167 " (((struct Library *)lh)->lib_OpenCnt == 0)\n"
1168 " && (((struct Library *)lh)->lib_Flags & LIBF_DELEXP)\n"
1169 " )\n"
1170 " {\n"
1171 " return AROS_LC1(BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1172 " AROS_LCA(LIBBASETYPEPTR, lh, D0),\n"
1173 " LIBBASETYPEPTR, lh, 3, %s\n"
1174 " );\n"
1175 " }\n",
1176 cfg->basename
1178 fprintf(out,
1179 "\n"
1180 " return BNULL;\n"
1181 "\n"
1182 " AROS_LIBFUNC_EXIT\n"
1183 "}\n"
1184 "\n"
1189 static void writeexpungelib(FILE *out, struct config *cfg)
1191 fprintf(out,
1192 "AROS_LH1 (BPTR, GM_UNIQUENAME(ExpungeLib),\n"
1193 " AROS_LHA(LIBBASETYPEPTR, extralh, D0),\n"
1194 " LIBBASETYPEPTR, lh, 3, %s\n"
1195 ")\n",
1196 cfg->basename
1198 fprintf(out,
1199 "{\n"
1200 " AROS_LIBFUNC_INIT\n"
1201 "\n"
1203 if (!(cfg->options & OPTION_NOEXPUNGE))
1205 fprintf(out,
1206 "\n"
1207 " if ( ((struct Library *)lh)->lib_OpenCnt == 0 )\n"
1208 " {\n"
1209 " BPTR seglist = GM_SEGLIST_FIELD(lh);\n"
1210 "\n"
1211 " if(!set_call_libfuncs(SETNAME(EXPUNGELIB), -1, 1, lh))\n"
1212 " {\n"
1213 " ((struct Library *)lh)->lib_Flags |= LIBF_DELEXP;\n"
1214 " return BNULL;\n"
1215 " }\n"
1216 "\n"
1217 " Remove((struct Node *)lh);\n"
1218 "\n"
1219 " set_call_funcs(SETNAME(DTORS), 1, 0);\n"
1220 " set_call_funcs(SETNAME(EXIT), -1, 0);\n"
1222 if (cfg->classlist != NULL)
1223 fprintf(out, " set_call_libfuncs(SETNAME(CLASSESEXPUNGE), -1, 0, lh);\n");
1224 if (!(cfg->options & OPTION_NOAUTOLIB))
1225 fprintf(out, " set_close_libraries();\n"
1226 "#ifdef GM_OOPBASE_FIELD\n"
1227 " CloseLibrary((struct Library *)GM_OOPBASE_FIELD(lh));\n"
1228 "#endif\n"
1230 if (cfg->options & OPTION_PERTASKBASE)
1231 fprintf(out,
1232 " FreeTaskStorageSlot(__pertaskslot);\n"
1233 " __pertaskslot = 0;\n"
1235 fprintf(out,
1236 "\n"
1237 " __freebase(lh);\n"
1238 "\n"
1239 " return seglist;\n"
1240 " }\n"
1241 "\n"
1242 " ((struct Library *)lh)->lib_Flags |= LIBF_DELEXP;\n"
1245 fprintf(out,
1246 "\n"
1247 " return BNULL;\n"
1248 "\n"
1249 " AROS_LIBFUNC_EXIT\n"
1250 "}\n"
1251 "\n"
1256 static void writeextfunclib(FILE *out, struct config *cfg)
1258 fprintf(out,
1259 "AROS_LH0 (LIBBASETYPEPTR, GM_UNIQUENAME(ExtFuncLib),\n"
1260 " LIBBASETYPEPTR, lh, 4, %s\n"
1261 ")\n"
1262 "{\n"
1263 " AROS_LIBFUNC_INIT\n"
1264 " return NULL;\n"
1265 " AROS_LIBFUNC_EXIT\n"
1266 "}\n"
1267 "\n",
1268 cfg->basename
1273 static void
1274 writefunctable(FILE *out,
1275 struct config *cfg
1278 struct functionhead *funclistit = cfg->funclist;
1279 struct functionarg *arglistit;
1280 unsigned int lvo;
1281 int i;
1282 char *name, *type;
1283 int lastversion = 0;
1285 /* lvo contains the number of functions already printed in the functable */
1286 lvo = 0;
1288 if (!(cfg->options & OPTION_NORESIDENT))
1290 fprintf(out,
1291 "\n"
1292 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1293 "{\n"
1295 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
1297 fprintf(out,
1298 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(OpenLib),%s,1),\n"
1299 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(CloseLib),%s,2),\n"
1300 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExpungeLib),%s,3),\n"
1301 " &AROS_SLIB_ENTRY(GM_UNIQUENAME(ExtFuncLib),%s,4),\n",
1302 cfg->basename, cfg->basename, cfg->basename, cfg->basename
1304 lvo += 4;
1306 if (cfg->modtype == MCC || cfg->modtype == MUI || cfg->modtype == MCP)
1308 lvo++;
1309 fprintf(out,
1310 " &AROS_SLIB_ENTRY(MCC_Query,%s,%d),\n",
1311 cfg->basename, lvo
1314 else if (cfg->modtype == DATATYPE)
1316 lvo++;
1317 fprintf(out,
1318 " &AROS_SLIB_ENTRY(ObtainEngine,%s,%d),\n",
1319 cfg->basename, lvo
1323 else /* NORESIDENT */
1325 if (cfg->modtype != RESOURCE && cfg->modtype != HANDLER)
1327 int neednull = 0;
1328 struct functionhead *funclistit2;
1330 if (funclistit->lvo != 1)
1332 fprintf(stderr, "Module without a generated resident structure has to provide the Open function (LVO==1)\n");
1333 exit(20);
1335 else
1336 funclistit = funclistit->next;
1338 if (funclistit->lvo != 2)
1340 fprintf(stderr, "Module without a generated resident structure has to provide the Close function (LVO==2)\n");
1341 exit(20);
1343 else
1344 funclistit = funclistit->next;
1346 if (funclistit->lvo == 3)
1347 funclistit = funclistit->next;
1348 else
1349 neednull = 1;
1351 if (funclistit->lvo == 4)
1352 funclistit = funclistit->next;
1353 else
1354 neednull = 1;
1356 if (neednull)
1357 fprintf(out,
1358 "\n"
1359 "AROS_UFH1S(int, %s_null,\n"
1360 " AROS_UFHA(struct Library *, libbase, A6)\n"
1361 ")\n"
1362 "{\n"
1363 " AROS_USERFUNC_INIT\n"
1364 " return 0;\n"
1365 " AROS_USERFUNC_EXIT\n"
1366 "}\n",
1367 cfg->modulename
1370 funclistit = cfg->funclist;
1371 funclistit2 = funclistit->next;
1372 fprintf(out,
1373 "\n"
1374 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1375 "{\n"
1376 " &AROS_SLIB_ENTRY(%s,%s,%d),\n"
1377 " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1378 funclistit->internalname, cfg->basename, lvo+1,
1379 funclistit2->internalname, cfg->basename, lvo+2
1381 lvo += 2;
1382 funclistit = funclistit2->next;
1384 if (funclistit->lvo == 3)
1386 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1387 funclistit->internalname, cfg->basename, lvo+1
1389 funclistit = funclistit->next;
1391 else
1392 fprintf(out, " &%s_null,\n", cfg->modulename);
1393 lvo++;
1395 if (funclistit->lvo == 4)
1397 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n",
1398 funclistit->internalname, cfg->basename, lvo+1
1400 funclistit = funclistit->next;
1402 else
1403 fprintf(out, " &%s_null,\n", cfg->modulename);
1404 lvo++;
1406 else
1408 fprintf(out,
1409 "\n"
1410 "const APTR GM_UNIQUENAME(FuncTable)[]=\n"
1411 "{\n");
1415 while (funclistit != NULL)
1417 for (i = lvo+1; i<funclistit->lvo; i++)
1418 fprintf(out, " NULL,\n");
1419 lvo = funclistit->lvo;
1421 switch (funclistit->libcall)
1423 case STACK:
1424 fprintf(out, " &%s,\n", funclistit->internalname
1426 break;
1428 case REGISTER:
1429 case REGISTERMACRO:
1430 if (funclistit->version != lastversion) {
1431 lastversion = funclistit->version;
1432 fprintf(out, " /* Version %d */\n", lastversion);
1434 fprintf(out, " &AROS_SLIB_ENTRY(%s,%s,%d),\n", funclistit->internalname, cfg->basename, lvo);
1435 break;
1437 default:
1438 fprintf(stderr, "Internal error: unhandled libcall type in writestart\n");
1439 exit(20);
1440 break;
1443 funclistit = funclistit->next;
1446 fprintf(out, " (void *)-1\n};\n");
1450 static void writesets(FILE *out, struct config *cfg)
1452 fprintf(out,
1453 "DEFINESET(INIT)\n"
1454 "DEFINESET(EXIT)\n"
1455 "DEFINESET(CTORS)\n"
1456 "DEFINESET(DTORS)\n"
1458 if (cfg->modtype != HANDLER)
1459 fprintf(out,
1460 "DEFINESET(INITLIB)\n"
1461 "DEFINESET(EXPUNGELIB)\n"
1463 if (!(cfg->options & OPTION_NOOPENCLOSE))
1464 fprintf(out,
1465 "DEFINESET(OPENLIB)\n"
1466 "DEFINESET(CLOSELIB)\n"
1468 if (cfg->modtype == DEVICE)
1469 fprintf(out,
1470 "DEFINESET(OPENDEV)\n"
1471 "DEFINESET(CLOSEDEV)\n"
1473 if (cfg->classlist != NULL)
1474 fprintf(out,
1475 "DEFINESET(CLASSESINIT)\n"
1476 "DEFINESET(CLASSESEXPUNGE)\n"
1478 fprintf(out, "\n");