2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Code to parse the command line options and the module config file for
16 #include "functionhead.h"
19 const static char bannertemplate
[] =
21 " *** Automatically generated from '%s'. Edits will be lost. ***\n"
22 " Copyright © 1995-2011, The AROS Development Team. All rights reserved.\n"
26 getBanner(struct config
* config
)
28 int bannerlength
= strlen(config
->conffile
) + strlen(bannertemplate
) -1;
29 char * banner
= malloc(bannerlength
);
31 snprintf (banner
, bannerlength
, bannertemplate
, config
->conffile
);
37 freeBanner(char *banner
)
42 const static char usage
[] =
44 "Usage: genmodule [-c conffile] [-s suffix] [-d gendir] [-n]\n"
45 " {writefiles|writemakefile|writeincludes|writelibdefs|writefunclist} modname modtype\n"
48 static void readconfig(struct config
*);
49 static struct classinfo
*newclass(struct config
*);
51 /* the method prefices for the supported classes */
52 static const char *muimprefix
[] =
58 static const char *gadgetmprefix
[] =
65 static const char *dtmprefix
[] =
74 /* Create a config struct. Initialize with the values from the programs command
75 * line arguments and the contents of the modules .conf file
77 struct config
*initconfig(int argc
, char **argv
)
80 char *s
, **argvit
= argv
+ 1;
83 cfg
= malloc(sizeof(struct config
));
86 fprintf(stderr
, "Out of memory\n");
90 memset(cfg
, 0, sizeof(struct config
));
92 while ((c
= getopt(argc
, argv
, ":c:s:d:")) != -1)
96 fprintf(stderr
, "Option -%c needs an argument\n",optopt
);
103 cfg
->conffile
= optarg
;
106 cfg
->suffix
= optarg
;
110 /* Remove / at end if present */
111 if ((optarg
)[strlen(*argvit
)-1]=='/') (optarg
)[strlen(optarg
)-1]='\0';
112 cfg
->gendir
= optarg
;
115 fprintf(stderr
, "Internal error: Unhandled option\n");
120 if (optind
+ 3 != argc
)
122 fprintf(stderr
, "Wrong number of arguments.\n%s", usage
);
126 if (strcmp(argv
[optind
], "writefiles") == 0)
128 cfg
->command
= FILES
;
130 else if (strcmp(argv
[optind
], "writemakefile") == 0)
132 cfg
->command
= MAKEFILE
;
134 else if (strcmp(argv
[optind
], "writeincludes") == 0)
136 cfg
->command
= INCLUDES
;
138 else if (strcmp(argv
[optind
], "writelibdefs") == 0)
140 cfg
->command
= LIBDEFS
;
142 else if (strcmp(argv
[optind
], "writefunclist") == 0)
144 cfg
->command
= WRITEFUNCLIST
;
148 fprintf(stderr
, "Unrecognized argument \"%s\"\n%s", argv
[optind
], usage
);
152 cfg
->modulename
= argv
[optind
+1];
153 cfg
->modulenameupper
= strdup(cfg
->modulename
);
154 for (s
=cfg
->modulenameupper
; *s
!='\0'; *s
= toupper(*s
), s
++)
157 if (strcmp(argv
[optind
+2],"library")==0)
159 cfg
->modtype
= LIBRARY
;
160 cfg
->moddir
= "Libs";
162 else if (strcmp(argv
[optind
+2],"mcc")==0)
165 cfg
->moddir
= "Classes/Zune";
167 else if (strcmp(argv
[optind
+2],"mui")==0)
170 cfg
->moddir
= "Classes/Zune";
172 else if (strcmp(argv
[optind
+2],"mcp")==0)
175 cfg
->moddir
= "Classes/Zune";
177 else if (strcmp(argv
[optind
+2], "device")==0)
179 cfg
->modtype
= DEVICE
;
180 cfg
->moddir
= "Devs";
182 else if (strcmp(argv
[optind
+2], "resource")==0)
184 cfg
->modtype
= RESOURCE
;
185 cfg
->moddir
= "Devs";
187 else if (strcmp(argv
[optind
+2], "gadget")==0)
189 cfg
->modtype
= GADGET
;
190 cfg
->moddir
= "Classes/Gadgets";
192 else if (strcmp(argv
[optind
+2], "datatype")==0)
194 cfg
->modtype
= DATATYPE
;
195 cfg
->moddir
= "Classes/Datatypes";
197 else if (strcmp(argv
[optind
+2], "usbclass")==0)
199 cfg
->modtype
= USBCLASS
;
200 cfg
->moddir
= "Classes/USB";
203 cfg
->suffix
= "class";
207 else if (strcmp(argv
[optind
+2], "hidd")==0)
210 cfg
->moddir
= "Devs/Drivers";
214 fprintf(stderr
, "Unknown modtype \"%s\" specified for second argument\n", argv
[2]);
219 cfg
->suffix
= argv
[optind
+2];
221 /* Fill fields with default value if not specified on the command line */
225 if (cfg
->conffile
== NULL
)
227 snprintf(tmpbuf
, sizeof(tmpbuf
), "%s.conf", cfg
->modulename
);
228 cfg
->conffile
= strdup(tmpbuf
);
231 if (cfg
->gendir
== NULL
)
237 /* For a device add the functions given in beginiofunc and abortiofunc to the functionlist
238 * if they are provided
240 if (cfg
->beginiofunc
!= NULL
)
242 struct functionhead
*funchead
;
244 cfg
->intcfg
|= CFG_NOREADFUNCS
;
246 /* Add beginio_func to the list of functions */
247 funchead
= newfunctionhead(cfg
->beginiofunc
, REGISTERMACRO
);
248 funchead
->type
= strdup("void");
250 funcaddarg(funchead
, "struct IORequest *ioreq", "A1");
252 funchead
->next
= cfg
->funclist
;
253 cfg
->funclist
= funchead
;
255 /* Add abortio_func to the list of functions */
256 funchead
= newfunctionhead(cfg
->abortiofunc
, REGISTERMACRO
);
257 funchead
->type
= strdup("LONG");
259 funcaddarg(funchead
, "struct IORequest *ioreq", "A1");
261 funchead
->next
= cfg
->funclist
->next
;
262 cfg
->funclist
->next
= funchead
;
264 else if (cfg
->modtype
== DEVICE
&& cfg
->intcfg
& CFG_NOREADFUNCS
)
269 "beginio_func and abortio_func missing for a device with a non empty function list\n"
277 /* Functions to read configuration from the configuration file */
279 #include "fileread.h"
281 static char *readsections(struct config
*, struct classinfo
*, int);
282 static void readsectionconfig(struct config
*, struct classinfo
*, int);
283 static void readsectioncdef(struct config
*);
284 static void readsectioncdefprivate(struct config
*);
285 static void readsectionstartup(struct config
*);
286 static void readsectionfunctionlist(struct config
*);
287 static void readsectionmethodlist(struct classinfo
*);
288 static void readsectionclass(struct config
*);
290 static void readconfig(struct config
*cfg
)
292 struct classinfo
*mainclass
= NULL
;
294 /* Create a classinfo structure if this module is a class */
295 switch (cfg
->modtype
)
309 mainclass
= newclass(cfg
);
310 mainclass
->classtype
= cfg
->modtype
;
314 fprintf(stderr
, "Internal error: unsupported modtype for classinfo creation\n");
318 switch (cfg
->modtype
)
331 mainclass
->boopsimprefix
= muimprefix
;
338 mainclass
->boopsimprefix
= gadgetmprefix
;
342 mainclass
->boopsimprefix
= dtmprefix
;
346 /* FIXME: need boopsimprefix ? */
349 fprintf(stderr
, "Internal error: unsupported modtype for firstlvo\n");
353 if (!fileopen(cfg
->conffile
))
355 fprintf(stderr
, "In readconfig: Could not open %s\n", cfg
->conffile
);
359 /* Read all sections and see that we are at the end of the file */
360 if (readsections(cfg
, mainclass
, 0) != NULL
)
361 exitfileerror(20, "Syntax error");
366 /* readsections will scan through all the sections in the config file.
368 * struct config *cfg: The module config data which may be updated by
369 * the information in the sections
370 * struct classinfo *cl: The classdata to be filled with data from the sections.
371 * This may be NULL if this is the main part of the configuration file and the
372 * type of the module is not a class
373 * int inclass: Boolean to indicate if we are in a class part. If not we are in the main
374 * part of the config file.
376 static char *readsections(struct config
*cfg
, struct classinfo
*cl
, int inclass
)
381 while ((line
=readline())!=NULL
)
383 if (strncmp(line
, "##", 2)==0)
385 static char *parts
[] =
387 "config", "cdefprivate", "cdef", "startup", "functionlist", "methodlist", "class"
389 const unsigned int nums
= sizeof(parts
)/sizeof(char *);
390 unsigned int partnum
;
394 while (isspace(*s
)) s
++;
396 if (strncmp(s
, "begin", 5)!=0)
401 exitfileerror(20, "space after begin expected\n");
402 while (isspace(*s
)) s
++;
404 for (i
= 0, partnum
= 0; partnum
==0 && i
<nums
; i
++)
406 if (strncmp(s
, parts
[i
], strlen(parts
[i
]))==0)
409 s
+= strlen(parts
[i
]);
410 while (isspace(*s
)) s
++;
412 exitfileerror(20, "unexpected character on position %d\n", s
-line
);
416 exitfileerror(20, "unknown start of section\n");
420 readsectionconfig(cfg
, cl
, inclass
);
424 case 2: /* cdefprivate */
426 exitfileerror(20, "cdefprivate section not allowed in class section\n");
427 readsectioncdefprivate(cfg
);
432 exitfileerror(20, "cdef section not allowed in class section\n");
433 readsectioncdef(cfg
);
436 case 4: /* startup */
438 exitfileerror(20, "startup section not allowed in class section\n");
439 readsectionstartup(cfg
);
442 case 5: /* functionlist */
444 exitfileerror(20, "functionlist section not allow in class section\n");
445 readsectionfunctionlist(cfg
);
446 cfg
->intcfg
|= CFG_NOREADFUNCS
;
449 case 6: /* methodlist */
451 exitfileerror(20, "methodlist section when not in a class\n");
452 readsectionmethodlist(cl
);
453 cfg
->intcfg
|= CFG_NOREADFUNCS
;
458 exitfileerror(20, "class section may not be nested\n");
459 readsectionclass(cfg
);
463 else if (strlen(line
)!=0)
464 filewarning("warning line outside section ignored\n");
470 exitfileerror(20, "No config section in conffile\n");
472 /* If no indication was given for generating includes or not
473 decide on module type and if there are functions
475 if(!((cfg
->options
& OPTION_INCLUDES
) || (cfg
->options
& OPTION_NOINCLUDES
)))
477 switch (cfg
->modtype
)
482 cfg
->options
|= OPTION_INCLUDES
;
487 (cfg
->funclist
!= NULL
)
488 || (cfg
->cdeflines
!= NULL
)
489 || strcmp(cfg
->libbasetypeptrextern
, "struct Device *") != 0
490 ) ? OPTION_INCLUDES
: OPTION_NOINCLUDES
;
500 (cfg
->funclist
!= NULL
)
501 || (cfg
->cdeflines
!= NULL
)
502 ) ? OPTION_INCLUDES
: OPTION_NOINCLUDES
;
506 fprintf(stderr
, "Internal error writemakefile: unhandled modtype for includes\n");
512 /* If no indication was given for not generating stubs only generate them if
513 * the module has functions
515 if(!((cfg
->options
& OPTION_STUBS
) || (cfg
->options
& OPTION_NOSTUBS
)))
517 cfg
->options
|= (cfg
->funclist
!= NULL
) ?
518 OPTION_STUBS
: OPTION_NOSTUBS
;
521 /* If no indication was given for generating autoinit code or not
522 decide on module type
524 if(!((cfg
->options
& OPTION_AUTOINIT
) || (cfg
->options
& OPTION_NOAUTOINIT
)))
526 switch (cfg
->modtype
)
530 cfg
->options
|= OPTION_AUTOINIT
;
541 cfg
->options
|= OPTION_NOAUTOINIT
;
545 fprintf(stderr
, "Internal error writemakefile: unhandled modtype for autoinit\n");
551 if (cfg
->modtype
== RESOURCE
)
552 /* Enforce noopenclose for resources */
553 cfg
->options
|= OPTION_NOOPENCLOSE
;
555 /* Enforce using RTF_AUTOINIT for everything except resources */
556 if (!(cfg
->options
& OPTION_SELFINIT
))
557 cfg
->options
|= OPTION_RESAUTOINIT
;
563 static void readsectionconfig(struct config
*cfg
, struct classinfo
*cl
, int inclass
)
566 char *line
, *s
, *s2
, *libbasetypeextern
= NULL
;
573 exitfileerror(20, "unexpected end of file in section config\n");
575 if (strncmp(line
, "##", 2)!=0)
577 const char *names
[] =
579 "basename", "libbase", "libbasetype", "libbasetypeextern",
580 "version", "date", "copyright", "libcall", "forcebase", "superclass",
581 "superclass_field", "residentpri", "options", "sysbase_field",
582 "seglist_field", "rootbase_field", "classptr_field", "classptr_var",
583 "classid", "classdatatype", "beginio_func", "abortio_func", "dispatcher",
584 "initpri", "type", "getidfunc", "addromtag"
586 const unsigned int namenums
= sizeof(names
)/sizeof(char *);
587 unsigned int namenum
;
589 for (i
= 0, namenum
= 0; namenum
==0 && i
<namenums
; i
++)
593 strncmp(line
, names
[i
], strlen(names
[i
]))==0
594 && isspace(*(line
+strlen(names
[i
])))
599 exitfileerror(20, "unrecognized configuration option\n");
601 s
= line
+ strlen(names
[namenum
-1]);
603 exitfileerror(20, "space character expected after \"%s\"\n", names
[namenum
-1]);
605 while (isspace(*s
)) s
++;
607 exitfileerror(20, "unexpected end of line\n");
610 while (isspace(*(s2
-1))) s2
--;
615 case 1: /* basename */
617 cfg
->basename
= strdup(s
);
619 cl
->basename
= strdup(s
);
622 case 2: /* libbase */
624 exitfileerror(20, "libbase not valid config option when in a class section\n");
625 cfg
->libbase
= strdup(s
);
628 case 3: /* libbasetype */
630 exitfileerror(20, "libbasetype not valid config option when in a class section\n");
631 cfg
->libbasetype
= strdup(s
);
634 case 4: /* libbasetypeextern */
636 exitfileerror(20, "libbasetype not valid config option when in a class section\n");
637 libbasetypeextern
= strdup(s
);
640 case 5: /* version */
642 exitfileerror(20, "version not valid config option when in a class section\n");
643 if (sscanf(s
, "%u.%u", &cfg
->majorversion
, &cfg
->minorversion
)!=2)
644 exitfileerror(20, "wrong version string \"%s\"\n", s
);
649 exitfileerror(20, "date not valid config option when in a class section\n");
651 if (strptime(s
, "%e.%m.%Y", &date
) == NULL
)
653 exitfileerror(20, "date string has to have d.m.yyyy format\n");
656 cfg
->datestring
= strdup(s
);
659 case 7: /* copyright */
661 exitfileerror(20, "copyright not valid config option when in a class section\n");
662 cfg
->copyright
= strdup(s
);
665 case 8: /* libcall */
666 fprintf(stderr
, "libcall specification is deprecated and ignored\n");
669 case 9: /* forcebase */
671 exitfileerror(20, "forcebase not valid config option when in a class section\n");
672 slist_append(&cfg
->forcelist
, s
);
675 case 10: /* superclass */
677 exitfileerror(20, "superclass specified when not a BOOPSI class\n");
678 cl
->superclass
= strdup(s
);
681 case 11: /* superclass_field */
683 exitfileerror(20, "superclass_field specified when not a BOOPSI class\n");
684 cl
->superclass_field
= strdup(s
);
687 case 12: /* residentpri */
693 count
= sscanf(s
, "%d%c", &cfg
->residentpri
, &dummy
);
695 cfg
->residentpri
< -128 || cfg
->residentpri
> 127
698 exitfileerror(20, "residentpri number format error\n");
702 exitfileerror(20, "residentpri not valid config option when in a class section\n");
705 case 13: /* options */
708 static const char *optionnames
[] =
710 "noautolib", "noexpunge", "noresident", "peropenerbase",
711 "peridbase", "includes", "noincludes", "nostubs",
712 "autoinit", "noautoinit", "resautoinit", "noopenclose",
715 const unsigned int optionnums
= sizeof(optionnames
)/sizeof(char *);
720 for (i
= 0, optionnum
= 0; optionnum
==0 && i
<optionnums
; i
++)
722 if (strncmp(s
, optionnames
[i
], strlen(optionnames
[i
]))==0)
725 s
+= strlen(optionnames
[i
]);
726 while (isspace(*s
)) s
++;
730 exitfileerror(20, "Unrecognized option\n");
734 exitfileerror(20, "Unrecognized option\n");
737 case 1: /* noautolib */
738 cfg
->options
|= OPTION_NOAUTOLIB
;
740 case 2: /* noexpunge */
741 cfg
->options
|= OPTION_NOEXPUNGE
;
743 case 3: /* noresident */
744 cfg
->options
|= OPTION_NORESIDENT
;
747 case 5: /* peridbase */
748 cfg
->options
|= OPTION_DUPPERID
;
750 case 4: /* peropenerbase */
751 if (cfg
->options
& OPTION_DUPBASE
)
752 exitfileerror(20, "Only one option peropenerbase or peridbase allowed\n");
753 cfg
->options
|= OPTION_DUPBASE
;
755 case 6: /* includes */
756 if (cfg
->options
& OPTION_NOINCLUDES
)
757 exitfileerror(20, "option includes and noincludes are incompatible\n");
758 cfg
->options
|= OPTION_INCLUDES
;
760 case 7: /* noincludes */
761 if (cfg
->options
& OPTION_INCLUDES
)
762 exitfileerror(20, "option includes and noincludes are incompatible\n");
763 cfg
->options
|= OPTION_NOINCLUDES
;
765 case 8: /* nostubs */
766 cfg
->options
|= OPTION_NOSTUBS
;
768 case 9: /* autoinit */
769 if (cfg
->options
& OPTION_NOAUTOINIT
)
770 exitfileerror(20, "option autoinit and noautoinit are incompatible\n");
771 cfg
->options
|= OPTION_AUTOINIT
;
773 case 10: /* noautoinit */
774 if (cfg
->options
& OPTION_AUTOINIT
)
775 exitfileerror(20, "option autoinit and noautoinit are incompatible\n");
776 cfg
->options
|= OPTION_NOAUTOINIT
;
778 case 11: /* resautoinit */
779 if (cfg
->options
& OPTION_SELFINIT
)
780 exitfileerror(20, "option resautoinit and selfinit are incompatible\n");
781 cfg
->options
|= OPTION_RESAUTOINIT
;
784 cfg
->options
|= OPTION_NOOPENCLOSE
;
786 case 13: /* noresautoinit */
787 if (cfg
->options
& OPTION_RESAUTOINIT
)
788 exitfileerror(20, "option resautoinit and selfinit are incompatible\n");
789 cfg
->options
|= OPTION_SELFINIT
;
792 while (isspace(*s
)) s
++;
797 static const char *optionnames
[] =
801 const unsigned int optionnums
= sizeof(optionnames
)/sizeof(char *);
806 for (i
= 0, optionnum
= 0; optionnum
==0 && i
<optionnums
; i
++)
808 if (strncmp(s
, optionnames
[i
], strlen(optionnames
[i
]))==0)
811 s
+= strlen(optionnames
[i
]);
812 while (isspace(*s
)) s
++;
816 exitfileerror(20, "Unrecognized option\n");
820 exitfileerror(20, "Unrecognized option\n");
823 case 1: /* private */
824 cl
->options
|= COPTION_PRIVATE
;
827 while (isspace(*s
)) s
++;
832 case 14: /* sysbase_field */
834 exitfileerror(20, "sysbase_field not valid config option when in a class section\n");
835 cfg
->sysbase_field
= strdup(s
);
838 case 15: /* seglist_field */
840 exitfileerror(20, "seglist_field not valid config option when in a class section\n");
841 cfg
->seglist_field
= strdup(s
);
844 case 16: /* rootbase_field */
846 exitfileerror(20, "rootbase_field not valid config option when in a class section\n");
847 cfg
->rootbase_field
= strdup(s
);
850 case 17: /* classptr_field */
856 "classptr_field specified when not a BOOPSI class\n"
859 cl
->classptr_field
= strdup(s
);
862 case 18: /* classptr_var */
868 "classptr_var specified when not a BOOPSI class\n"
871 cl
->classptr_var
= strdup(s
);
874 case 19: /* classid */
876 exitfileerror(20, "classid specified when not a BOOPSI class\n");
877 if (cl
->classid
!= NULL
)
878 exitfileerror(20, "classid specified twice\n");
879 cl
->classid
= strdup(s
);
880 if (strcmp(cl
->classid
, "NULL") == 0)
881 cl
->options
|= COPTION_PRIVATE
;
884 case 20: /* classdatatype */
886 exitfileerror(20, "classdatatype specified when not a BOOPSI class\n");
887 cl
->classdatatype
= strdup(s
);
890 case 21: /* beginio_func */
892 exitfileerror(20, "beginio_func not valid config option when in a class section\n");
893 if (cfg
->modtype
!= DEVICE
)
894 exitfileerror(20, "beginio_func specified when not a device\n");
895 cfg
->beginiofunc
= strdup(s
);
898 case 22: /* abortio_func */
900 exitfileerror(20, "abortio_func not valid config option when in a class section\n");
901 if (cfg
->modtype
!= DEVICE
)
902 exitfileerror(20, "abortio_func specified when not a device\n");
903 cfg
->abortiofunc
= strdup(s
);
906 case 23: /* dispatcher */
908 exitfileerror(20, "dispatcher specified when not a BOOPSI class\n");
909 cl
->dispatcher
= strdup(s
);
910 /* function references are not needed when dispatcher is specified */
911 cfg
->intcfg
|= CFG_NOREADFUNCS
;
914 case 24: /* initpri */
920 count
= sscanf(s
, "%d%c", &cl
->initpri
, &dummy
);
922 cl
->initpri
< -128 || cl
->initpri
> 127
925 exitfileerror(20, "initpri number format error\n");
929 exitfileerror(20, "initpri only valid config option for a BOOPSI class\n");
934 exitfileerror(20, "type only valid config option in a class section\n");
935 if (strcmp(s
,"mcc")==0)
937 else if (strcmp(s
,"mui")==0)
939 else if (strcmp(s
,"mcp")==0)
941 else if (strcmp(s
, "image")==0)
942 cl
->classtype
= IMAGE
;
943 else if (strcmp(s
, "gadget")==0)
944 cl
->classtype
= GADGET
;
945 else if (strcmp(s
, "datatype")==0)
946 cl
->classtype
= DATATYPE
;
947 else if (strcmp(s
, "usbclass")==0)
948 cl
->classtype
= USBCLASS
;
949 else if (strcmp(s
, "class")==0)
950 cl
->classtype
= CLASS
;
951 else if (strcmp(s
, "hidd")==0)
952 cl
->classtype
= HIDD
;
955 fprintf(stderr
, "Unknown type \"%s\" specified\n", s
);
959 case 26: /* getidfunc */
960 cfg
->getidfunc
= strdup(s
);
963 case 27: /* addromtag */
964 cfg
->addromtag
= strdup(s
);
968 else /* Line starts with ## */
971 while (isspace(*s
)) s
++;
972 if (strncmp(s
, "end", 3)!=0)
973 exitfileerror(20, "\"##end config\" expected\n");
977 exitfileerror(20, "\"##end config\" expected\n");
979 while (isspace(*s
)) s
++;
980 if (strncmp(s
, "config", 6)!=0)
981 exitfileerror(20, "\"##end config\" expected\n");
984 while (isspace(*s
)) s
++;
986 exitfileerror(20, "\"##end config\" expected\n");
992 /* When not in a class section fill in default values for fields in cfg */
995 if (cfg
->basename
==NULL
)
997 cfg
->basename
= strdup(cfg
->modulename
);
998 *cfg
->basename
= toupper(*cfg
->basename
);
1000 if (cfg
->libbase
==NULL
)
1002 unsigned int len
= strlen(cfg
->basename
)+5;
1003 cfg
->libbase
= malloc(len
);
1004 snprintf(cfg
->libbase
, len
, "%sBase", cfg
->basename
);
1006 if (cfg
->libbasetype
== NULL
&& libbasetypeextern
!= NULL
)
1007 cfg
->libbasetype
= strdup(libbasetypeextern
);
1008 if (cfg
->sysbase_field
!= NULL
&& cfg
->libbasetype
== NULL
)
1009 exitfileerror(20, "sysbase_field specified when no libbasetype is given\n");
1010 if (cfg
->seglist_field
!= NULL
&& cfg
->libbasetype
== NULL
)
1011 exitfileerror(20, "seglist_field specified when no libbasetype is given\n");
1012 /* rootbase_field only allowed when duplicating base */
1013 if (cfg
->rootbase_field
!= NULL
&& !(cfg
->options
& OPTION_DUPBASE
))
1014 exitfileerror(20, "rootbasefield only valid for option peropenerbase or peridbase\n");
1015 if (cfg
->getidfunc
!= NULL
&& !(cfg
->options
& OPTION_DUPPERID
))
1016 exitfileerror(20, "getidfunc only valid for option peridbase\n");
1018 /* Set default date to current date */
1019 if (cfg
->datestring
== NULL
)
1022 time_t now
= time(NULL
);
1023 struct tm
*ltime
= localtime(&now
);
1025 snprintf(tmpbuf
, sizeof(tmpbuf
), "%u.%u.%u",
1026 ltime
->tm_mday
, 1 + ltime
->tm_mon
, 1900 + ltime
->tm_year
);
1028 cfg
->datestring
= strdup(tmpbuf
);
1031 if (cfg
->copyright
== NULL
)
1032 cfg
->copyright
= "";
1034 if ( (cfg
->beginiofunc
!= NULL
&& cfg
->abortiofunc
== NULL
)
1035 || (cfg
->beginiofunc
== NULL
&& cfg
->abortiofunc
!= NULL
)
1037 exitfileerror(20, "please specify both beginio_func and abortio_func\n");
1039 if (libbasetypeextern
==NULL
)
1041 switch (cfg
->modtype
)
1044 cfg
->libbasetypeptrextern
= "struct Device *";
1047 cfg
->libbasetypeptrextern
= "APTR ";
1057 cfg
->libbasetypeptrextern
= "struct Library *";
1060 fprintf(stderr
, "Internal error: Unsupported modtype for libbasetypeptrextern\n");
1066 cfg
->libbasetypeptrextern
= malloc(strlen(libbasetypeextern
)+3);
1067 strcpy(cfg
->libbasetypeptrextern
, libbasetypeextern
);
1068 strcat(cfg
->libbasetypeptrextern
, " *");
1069 free(libbasetypeextern
);
1073 /* When class was given too fill in some defaults when not specified */
1076 if (cl
->classtype
== UNSPECIFIED
)
1077 cl
->classtype
= CLASS
;
1079 if (cl
->basename
== NULL
)
1082 cl
->basename
= cfg
->basename
;
1084 exitfileerror(20, "basename has to be specified in the config section inside of a class section\n");
1087 /* MUI classes are always private */
1088 if (cl
->classtype
== MUI
|| cl
->classtype
== MCC
|| cl
->classtype
== MCP
)
1089 cl
->options
|= COPTION_PRIVATE
;
1091 if (cl
->classid
== NULL
1092 && (cl
->classtype
!= MUI
&& cl
->classtype
!= MCC
&& cl
->classtype
!= MCP
)
1095 if (cl
->classtype
== HIDD
)
1097 cl
->options
&= !COPTION_PRIVATE
;
1099 else if (cl
->options
& COPTION_PRIVATE
)
1101 cl
->classid
= "NULL";
1107 if (cl
->classtype
== GADGET
|| cl
->classtype
== IMAGE
|| cl
->classtype
== CLASS
|| cl
->classtype
== USBCLASS
)
1109 sprintf(s
, "\"%sclass\"", inclass
? cl
->basename
: cfg
->modulename
);
1111 else if (cl
->classtype
== DATATYPE
)
1113 sprintf(s
, "\"%s.datatype\"", inclass
? cl
->basename
: cfg
->modulename
);
1115 cl
->classid
= strdup(s
);
1119 /* Only specify superclass or superclass_field */
1120 if (cl
->superclass
!= NULL
&& cl
->superclass_field
!= NULL
)
1121 exitfileerror(20, "Only specify one of superclass or superclass_field in config section\n");
1123 /* Give default value to superclass if it is not specified */
1124 if (cl
->superclass
== NULL
&& cl
->superclass
== NULL
)
1126 switch (cl
->classtype
)
1130 cl
->superclass
= "MUIC_Area";
1133 cl
->superclass
= "MUIC_Mccprefs";
1136 cl
->superclass
= "IMAGECLASS";
1139 cl
->superclass
= "GADGETCLASS";
1142 cl
->superclass
= "DATATYPESCLASS";
1145 cl
->superclass
= "ROOTCLASS";
1148 cl
->superclass
= "CLID_Root";
1151 exitfileerror(20, "Internal error: unhandled classtype in readsectionconfig\n");
1158 static void readsectioncdef(struct config
*cfg
)
1167 exitfileerror(20, "unexptected end of file in section cdef\n");
1169 if (strncmp(line
, "##", 2)!=0)
1171 slist_append(&cfg
->cdeflines
, line
);
1176 while (isspace(*s
)) s
++;
1177 if (strncmp(s
, "end", 3)!=0)
1178 exitfileerror(20, "\"##end cdef\" expected\n");
1181 while (isspace(*s
)) s
++;
1182 if (strncmp(s
, "cdef", 4)!=0)
1183 exitfileerror(20, "\"##end cdef\" expected\n");
1186 while (isspace(*s
)) s
++;
1188 exitfileerror(20, "unexpected character at position %d\n");
1195 static void readsectioncdefprivate(struct config
*cfg
)
1204 exitfileerror(20, "unexptected end of file in section cdef\n");
1206 if (strncmp(line
, "##", 2)!=0)
1208 slist_append(&cfg
->cdefprivatelines
, line
);
1213 while (isspace(*s
)) s
++;
1214 if (strncmp(s
, "end", 3)!=0)
1215 exitfileerror(20, "\"##end cdefprivate\" expected\n");
1218 while (isspace(*s
)) s
++;
1219 if (strncmp(s
, "cdefprivate", 11)!=0)
1220 exitfileerror(20, "\"##end cdefprivate\" expected\n");
1223 while (isspace(*s
)) s
++;
1225 exitfileerror(20, "unexpected character at position %d\n");
1232 static void readsectionstartup(struct config
*cfg
)
1241 exitfileerror(20, "unexptected end of file in section startup\n");
1243 if (strncmp(line
, "##", 2)!=0)
1245 slist_append(&cfg
->startuplines
, line
);
1250 while (isspace(*s
)) s
++;
1251 if (strncmp(s
, "end", 3)!=0)
1252 exitfileerror(20, "\"##end startup\" expected\n");
1255 while (isspace(*s
)) s
++;
1256 if (strncmp(s
, "startup", 7)!=0)
1257 exitfileerror(20, "\"##end startup\" expected\n");
1260 while (isspace(*s
)) s
++;
1262 exitfileerror(20, "unexpected character at position %d\n");
1269 static void readsectionfunctionlist(struct config
*cfg
)
1272 char *line
, *s
, *s2
;
1273 unsigned int lvo
= cfg
->firstlvo
;
1274 struct functionhead
**funclistptr
= &cfg
->funclist
;
1276 if (cfg
->basename
==NULL
)
1277 exitfileerror(20, "section functionlist has to come after section config\n");
1283 exitfileerror(20, "unexptected EOF in functionlist section\n");
1284 if (strlen(line
)==0)
1286 if (*funclistptr
!= NULL
)
1287 funclistptr
= &((*funclistptr
)->next
);
1290 else if (isspace(*line
))
1293 while (isspace(*s
)) s
++;
1296 if (*funclistptr
!= NULL
)
1297 funclistptr
= &((*funclistptr
)->next
);
1301 exitfileerror(20, "no space allowed before functionname\n");
1303 else if (strncmp(line
, "##", 2)==0)
1306 while (isspace(*s
)) s
++;
1307 if (strncmp(s
, "end", 3)!=0)
1308 exitfileerror(20, "\"##end functionlist\" expected\n");
1311 while (isspace(*s
)) s
++;
1312 if (strncmp(s
, "functionlist", 12)!=0)
1313 exitfileerror(20, "\"##end functionlist\" expected\n");
1316 while (isspace(*s
)) s
++;
1318 exitfileerror(20, "unexpected character on position %d\n", s
-line
);
1322 else if (*line
=='.')
1325 if (strncmp(s
, "skip", 4)==0)
1331 exitfileerror(20, "syntax is '.skip n'\n");
1333 n
=strtol(s
, &s2
, 10);
1335 exitfileerror(20, "positive number expected\n");
1337 while (isspace(*s2
)) s2
++;
1338 if ((*s2
!= '\0') && (*s2
!= '#'))
1339 exitfileerror(20, "syntax is '.skip n'\n");
1340 if (*funclistptr
!= NULL
)
1341 funclistptr
= &((*funclistptr
)->next
);
1344 else if (strncmp(s
, "alias", 5)==0)
1349 exitfileerror(20, "syntax is '.alias name'\n");
1351 while (isspace(*s
)) s
++;
1352 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1353 exitfileerror(20, "syntax is '.alias name'\n");
1357 while (isalnum(*s
) || *s
== '_') s
++;
1364 } while (isspace(*s
));
1368 exitfileerror(20, "syntax is '.alias name'\n");
1370 if (*funclistptr
== NULL
)
1371 exitfileerror(20, ".alias has to come after a function declaration\n");
1373 slist_append(&(*funclistptr
)->aliases
, s2
);
1375 else if (strncmp(s
, "function", 8) == 0)
1380 exitfileerror(20, "Syntax error\n");
1382 while (isspace(*s
)) s
++;
1383 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1384 exitfileerror(20, "syntax is '.function name'\n");
1388 while (isalnum(*s
) || *s
== '_') s
++;
1395 } while (isspace(*s
));
1399 exitfileerror(20, "syntax is '.function name'\n");
1401 if (*funclistptr
== NULL
)
1402 exitfileerror(20, ".function has to come after a function declaration\n");
1404 funcsetinternalname(*funclistptr
, s2
);
1406 else if (strncmp(s
, "cfunction", 9)==0)
1408 if (*funclistptr
== NULL
)
1409 exitfileerror(20, ".cfunction has to come after a function declaration\n");
1411 (*funclistptr
)->libcall
= REGISTER
;
1413 else if (strncmp(s
, "private", 7)==0)
1415 if (*funclistptr
== NULL
)
1416 exitfileerror(20, ".private has to come after a function declaration\n");
1418 (*funclistptr
)->priv
= 1;
1420 else if (strncmp(s
, "novararg", 8)==0)
1422 if (*funclistptr
== NULL
)
1423 exitfileerror(20, ".novararg has to come after a function declaration\n");
1425 (*funclistptr
)->novararg
= 1;
1428 exitfileerror(20, "Syntax error");
1430 else if (*line
!='#') /* Ignore line that is a comment, e.g. that starts with a # */
1432 /* The line is a function prototype. It can have two syntax
1433 * type funcname(argproto1, argproto2, ...)
1434 * type funcname(argproto1, argproto2, ...) (reg1, reg2, ...)
1435 * The former is for C type function argument passing, the latter for
1436 * register argument passing.
1438 char c
, *args
[64], *regs
[64], *funcname
;
1439 int len
, argcount
= 0, regcount
= 0, brcount
= 0;
1441 /* Parse 'type functionname' at the beginning of the line */
1442 s
= strchr(line
, '(');
1444 exitfileerror(20, "( expected at position %d\n", strlen(line
) + 1);
1447 while (isspace(*(s2
-1)))
1451 while (s2
> line
&& !isspace(*(s2
-1)) && !(*(s2
-1) == '*'))
1455 exitfileerror(20, "No type specifier before function name\n");
1457 if (*funclistptr
!= NULL
)
1458 funclistptr
= &((*funclistptr
)->next
);
1459 *funclistptr
= newfunctionhead(s2
, STACK
);
1461 while (isspace(*(s2
-1)))
1464 (*funclistptr
)->type
= strdup(line
);
1465 (*funclistptr
)->lvo
= lvo
;
1468 /* Parse function prototype */
1485 && !(brcount
== 0 && (*s
== ',' || *s
== ')'))
1495 exitfileerror(20, "Unexected ')' at position %d\n", s
-line
+1);
1502 exitfileerror(20, "'(' without ')'");
1505 while (isspace(*(s2
-1)))
1509 if (!(s2
> args
[argcount
- 1]))
1510 exitfileerror(20, "Syntax error in function prototype\n");
1516 while (*s
!= '\0' && isspace(*s
))
1521 /* Parse registers specifications if available otherwise this prototype for C type argument passing */
1523 /* There may be no register specified with () so be sure then c is == ')' */
1538 if (memchr("AD",s
[0],2)!=NULL
&& memchr("01234567",s
[1],8)!=NULL
)
1545 if (s
[0] == s
[-3] && s
[1] == s
[-2] + 1)
1552 "wrong register specification \"%s\" for argument %u\n",
1553 regs
[regcount
-1], regcount
1557 exitfileerror(20, "maximum two arguments passed in two registers allowed\n");
1563 "wrong register \"%s\" for argument %u\n",
1564 regs
[regcount
-1], regcount
1573 exitfileerror(20, "'(' without ')'\n");
1574 if (c
!= ',' && c
!= ')')
1575 exitfileerror(20, "',' or ')' expected at position %d\n", s
-line
+1);
1581 while (isspace(*s
)) s
++;
1583 exitfileerror(20, "wrong char '%c' at position %d\n", *s
, (int)(s
-line
) + 1);
1585 if (argcount
!= regcount
)
1586 exitfileerror(20, "Number of arguments (%d) and registers (%d) mismatch\n",
1590 (*funclistptr
)->libcall
= REGISTERMACRO
;
1591 for (i
= 0; i
< argcount
; i
++)
1592 funcaddarg(*funclistptr
, args
[i
], regs
[i
]);
1594 else if (*s
== '\0')
1595 { /* No registers specified */
1596 for (i
= 0; i
< argcount
; i
++)
1597 funcaddarg(*funclistptr
, args
[i
], NULL
);
1600 exitfileerror(20, "wrong char '%c' at position %d\n", *s
, (int)(s
-line
) + 1);
1605 static void readsectionmethodlist(struct classinfo
*cl
)
1608 char *line
, *s
, *s2
;
1609 struct functionhead
**methlistptr
= &cl
->methlist
;
1610 struct stringlist
*interface
= NULL
;
1612 if (cl
->basename
==NULL
)
1613 exitfileerror(20, "section methodlist has to come after section config\n");
1619 exitfileerror(20, "unexptected EOF in methodlist section\n");
1621 /* Ignore empty lines or lines that qre a comment, e.g. that starts with a # */
1622 if (strlen(line
)==0 || (line
[0] == '#' && line
[1] != '#'))
1626 exitfileerror(20, "No space allowed at start of the line\n");
1628 if (strncmp(line
, "##", 2)==0) /* Is this the end ? */
1631 while (isspace(*s
)) s
++;
1632 if (strncmp(s
, "end", 3)!=0)
1633 exitfileerror(20, "\"##end methodlist\" expected\n");
1636 while (isspace(*s
)) s
++;
1637 if (strncmp(s
, "methodlist", 10)!=0)
1638 exitfileerror(20, "\"##end methodlist\" expected\n");
1641 while (isspace(*s
)) s
++;
1643 exitfileerror(20, "unexpected character on position %d\n", s
-line
);
1653 if (strncmp(s
, "alias", 5)==0)
1658 exitfileerror(20, "syntax is '.alias name'\n");
1660 while (isspace(*s
)) s
++;
1661 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1662 exitfileerror(20, "syntax is '.alias name'\n");
1666 while (isalnum(*s
) || *s
== '_') s
++;
1673 } while (isspace(*s
));
1677 exitfileerror(20, "syntax is '.alias name'\n");
1679 if (*methlistptr
== NULL
)
1680 exitfileerror(20, ".alias has to come after a function declaration\n");
1682 slist_append(&(*methlistptr
)->aliases
, s2
);
1684 else if (strncmp(s
, "function", 8) == 0)
1689 exitfileerror(20, "Syntax error\n");
1691 while (isspace(*s
)) s
++;
1692 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1693 exitfileerror(20, "syntax is '.function name'\n");
1697 while (isalnum(*s
) || *s
== '_') s
++;
1704 } while (isspace(*s
));
1708 exitfileerror(20, "syntax is '.function name'\n");
1710 if (*methlistptr
== NULL
)
1711 exitfileerror(20, ".function has to come after a function declaration\n");
1713 funcsetinternalname(*methlistptr
, s2
);
1715 else if (strncmp(s
, "interface", 9) == 0)
1717 if (cl
->classtype
!= HIDD
)
1718 exitfileerror(20, "interface only valid for a HIDD\n");
1723 exitfileerror(20, "Syntax error\n");
1725 while (isspace(*s
)) s
++;
1726 if (*s
== '\0' || !isalpha(*s
))
1727 exitfileerror(20, "syntax is '.interface name'\n");
1731 while (isalnum(*s
) || *s
== '_') s
++;
1738 } while (isspace(*s
));
1742 exitfileerror(20, "syntax is '.interface name'\n");
1744 interface
= slist_append(&cl
->interfaces
, s2
);
1747 exitfileerror(20, "Syntax error");
1749 else if (isalpha(*line
))
1753 for (s
= line
+ 1; isalnum(*s
) || *s
== '_'; s
++)
1756 if (cl
->classtype
== HIDD
&& interface
== NULL
)
1757 exitfileerror(20, "For a HIDD the first method has to come after an .interface line\n");
1760 exitfileerror(20, "Only letters, digits and an underscore allowed in a methodname\n");
1762 if (*methlistptr
!= NULL
)
1763 methlistptr
= &((*methlistptr
)->next
);
1764 if (cl
->classtype
!= HIDD
)
1766 if (snprintf(stmp
, 256, "%s__%s", cl
->basename
, line
) >= 256)
1767 exitfileerror(20, "Method name too large\n");
1769 *methlistptr
= newfunctionhead(stmp
, STACK
);
1770 (*methlistptr
)->type
= "IPTR";
1771 funcaddarg(*methlistptr
, "Class *cl", NULL
);
1772 funcaddarg(*methlistptr
, "Object *o", NULL
);
1773 funcaddarg(*methlistptr
, "Msg msg", NULL
);
1777 if (snprintf(stmp
, 256, "%s__%s__%s", cl
->basename
, interface
->s
, line
) >= 256)
1778 exitfileerror(20, "Method name too large\n");
1780 *methlistptr
= newfunctionhead(stmp
, STACK
);
1781 (*methlistptr
)->type
= "IPTR";
1782 funcaddarg(*methlistptr
, "OOP_Class *cl", NULL
);
1783 funcaddarg(*methlistptr
, "OOP_Object *o", NULL
);
1784 funcaddarg(*methlistptr
, "OOP_Msg msg", NULL
);
1785 (*methlistptr
)->interface
= interface
;
1786 if (snprintf(stmp
, 256, "mo%s_%s", interface
->s
, line
) >= 256)
1787 exitfileerror(20, "Method name too large\n");
1788 (*methlistptr
)->method
= strdup(stmp
);
1790 slist_append(&(*methlistptr
)->aliases
, line
);
1793 exitfileerror(20, "Methodname has to begin with a letter\n");
1798 readsectionclass(struct config
*cfg
)
1801 struct classinfo
*cl
;
1804 s
= readsections(cfg
, cl
, 1);
1806 exitfileerror(20, "Unexpected end of file\n");
1808 if (strncmp(s
, "##", 2) != 0)
1809 exitfileerror(20, "'##end class' expected\n");
1812 while (isspace(*s
)) s
++;
1814 if (strncmp(s
, "end", 3) != 0)
1815 exitfileerror(20, "'##end class' expected\n");
1819 exitfileerror(20, "'##end class' expected\n");
1820 while (isspace(*s
)) s
++;
1822 if (strncmp(s
, "class", 5) != 0)
1823 exitfileerror(20, "'##end class' expected\n");
1826 while (isspace(*s
)) s
++;
1828 exitfileerror(20, "'##end class' expected\n");
1831 static struct classinfo
*newclass(struct config
*cfg
)
1833 struct classinfo
*cl
, *classlistit
;
1835 cl
= malloc(sizeof(struct classinfo
));
1838 fprintf(stderr
, "Out of memory\n");
1841 memset(cl
, 0, sizeof(struct classinfo
));
1843 /* By default the classes are initialized with a priority of 1 so they
1844 * are initialized before any user added initialization with priority 1
1848 if (cfg
->classlist
== NULL
)
1849 cfg
->classlist
= cl
;
1854 classlistit
= cfg
->classlist
;
1855 classlistit
->next
!= NULL
;
1856 classlistit
= classlistit
->next
1859 classlistit
->next
= cl
;