2 Copyright © 1995-2010, 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-2010, 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] [-r reffile] [-n]\n"
45 " {writefiles|writemakefile|writeincludes|writedummy|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:r:")) != -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 cfg
->reffile
= optarg
;
118 fprintf(stderr
, "Internal error: Unhandled option\n");
123 if (optind
+ 3 != argc
)
125 fprintf(stderr
, "Wrong number of arguments.\n%s", usage
);
129 if (strcmp(argv
[optind
], "writefiles") == 0)
131 cfg
->command
= FILES
;
133 else if (strcmp(argv
[optind
], "writemakefile") == 0)
135 cfg
->command
= MAKEFILE
;
137 else if (strcmp(argv
[optind
], "writeincludes") == 0)
139 cfg
->command
= INCLUDES
;
141 else if (strcmp(argv
[optind
], "writelibdefs") == 0)
143 cfg
->command
= LIBDEFS
;
145 else if (strcmp(argv
[optind
], "writedummy") == 0)
147 cfg
->command
= DUMMY
;
149 else if (strcmp(argv
[optind
], "writefunclist") == 0)
151 cfg
->command
= WRITEFUNCLIST
;
155 fprintf(stderr
, "Unrecognized argument \"%s\"\n%s", argv
[optind
], usage
);
159 cfg
->modulename
= argv
[optind
+1];
160 cfg
->modulenameupper
= strdup(cfg
->modulename
);
161 for (s
=cfg
->modulenameupper
; *s
!='\0'; *s
= toupper(*s
), s
++)
164 if (strcmp(argv
[optind
+2],"library")==0)
166 cfg
->modtype
= LIBRARY
;
167 cfg
->moddir
= "Libs";
169 else if (strcmp(argv
[optind
+2],"mcc")==0)
172 cfg
->moddir
= "Classes/Zune";
174 else if (strcmp(argv
[optind
+2],"mui")==0)
177 cfg
->moddir
= "Classes/Zune";
179 else if (strcmp(argv
[optind
+2],"mcp")==0)
182 cfg
->moddir
= "Classes/Zune";
184 else if (strcmp(argv
[optind
+2], "device")==0)
186 cfg
->modtype
= DEVICE
;
187 cfg
->moddir
= "Devs";
189 else if (strcmp(argv
[optind
+2], "resource")==0)
191 cfg
->modtype
= RESOURCE
;
192 cfg
->moddir
= "Devs";
194 else if (strcmp(argv
[optind
+2], "gadget")==0)
196 cfg
->modtype
= GADGET
;
197 cfg
->moddir
= "Classes/Gadgets";
199 else if (strcmp(argv
[optind
+2], "datatype")==0)
201 cfg
->modtype
= DATATYPE
;
202 cfg
->moddir
= "Classes/Datatypes";
204 else if (strcmp(argv
[optind
+2], "usbclass")==0)
206 cfg
->modtype
= USBCLASS
;
207 cfg
->moddir
= "Classes/USB";
210 cfg
->suffix
= "class";
214 else if (strcmp(argv
[optind
+2], "hidd")==0)
217 cfg
->moddir
= "Devs/Drivers";
221 fprintf(stderr
, "Unknown modtype \"%s\" specified for second argument\n", argv
[2]);
226 cfg
->suffix
= argv
[optind
+2];
228 /* Fill fields with default value if not specified on the command line */
232 if (cfg
->conffile
== NULL
)
234 snprintf(tmpbuf
, sizeof(tmpbuf
), "%s.conf", cfg
->modulename
);
235 cfg
->conffile
= strdup(tmpbuf
);
238 if (cfg
->gendir
== NULL
)
241 if (cfg
->command
!= FILES
&& cfg
->command
!= INCLUDES
&& cfg
->command
!= WRITEFUNCLIST
)
243 if (cfg
->reffile
!= NULL
)
244 fprintf(stderr
, "WARNING ! Option -r ingored for %s\n", argv
[optind
]);
246 else if (cfg
->command
== FILES
&& cfg
->reffile
== NULL
)
248 snprintf(tmpbuf
, sizeof(tmpbuf
), "%s.ref", cfg
->modulename
);
249 cfg
->reffile
= strdup(tmpbuf
);
255 /* For a device add the functions given in beginiofunc and abortiofunc to the functionlist
256 * if they are provided
258 if (cfg
->beginiofunc
!= NULL
)
260 struct functionhead
*funchead
;
262 cfg
->intcfg
|= CFG_NOREADREF
;
264 /* Add beginio_func to the list of functions */
265 funchead
= newfunctionhead(cfg
->beginiofunc
, REGISTERMACRO
);
266 funchead
->type
= strdup("void");
268 funcaddarg(funchead
, "struct IORequest *ioreq", "A1");
270 funchead
->next
= cfg
->funclist
;
271 cfg
->funclist
= funchead
;
273 /* Add abortio_func to the list of functions */
274 funchead
= newfunctionhead(cfg
->abortiofunc
, REGISTERMACRO
);
275 funchead
->type
= strdup("LONG");
277 funcaddarg(funchead
, "struct IORequest *ioreq", "A1");
279 funchead
->next
= cfg
->funclist
->next
;
280 cfg
->funclist
->next
= funchead
;
282 else if (cfg
->modtype
== DEVICE
&& cfg
->intcfg
& CFG_NOREADREF
)
287 "beginio_func and abortio_func missing for a device with a non empty function list\n"
295 /* Functions to read configuration from the configuration file */
297 #include "fileread.h"
299 static char *readsections(struct config
*, struct classinfo
*, int);
300 static void readsectionconfig(struct config
*, struct classinfo
*, int);
301 static void readsectioncdef(struct config
*);
302 static void readsectioncdefprivate(struct config
*);
303 static void readsectionstartup(struct config
*);
304 static void readsectionfunctionlist(struct config
*);
305 static void readsectionmethodlist(struct classinfo
*);
306 static void readsectionclass(struct config
*);
308 static void readconfig(struct config
*cfg
)
310 struct classinfo
*mainclass
= NULL
;
312 /* Create a classinfo structure if this module is a class */
313 switch (cfg
->modtype
)
327 mainclass
= newclass(cfg
);
328 mainclass
->classtype
= cfg
->modtype
;
332 fprintf(stderr
, "Internal error: unsupported modtype for classinfo creation\n");
336 switch (cfg
->modtype
)
349 mainclass
->boopsimprefix
= muimprefix
;
356 mainclass
->boopsimprefix
= gadgetmprefix
;
360 mainclass
->boopsimprefix
= dtmprefix
;
364 /* FIXME: need boopsimprefix ? */
367 fprintf(stderr
, "Internal error: unsupported modtype for firstlvo\n");
371 if (!fileopen(cfg
->conffile
))
373 fprintf(stderr
, "In readconfig: Could not open %s\n", cfg
->conffile
);
377 /* Read all sections and see that we are at the end of the file */
378 if (readsections(cfg
, mainclass
, 0) != NULL
)
379 exitfileerror(20, "Syntax error");
384 /* readsections will scan through all the sections in the config file.
386 * struct config *cfg: The module config data which may be updated by
387 * the information in the sections
388 * struct classinfo *cl: The classdata to be filled with data from the sections.
389 * This may be NULL if this is the main part of the configuration file and the
390 * type of the module is not a class
391 * int inclass: Boolean to indicate if we are in a class part. If not we are in the main
392 * part of the config file.
394 static char *readsections(struct config
*cfg
, struct classinfo
*cl
, int inclass
)
399 while ((line
=readline())!=NULL
)
401 if (strncmp(line
, "##", 2)==0)
403 static char *parts
[] =
405 "config", "cdefprivate", "cdef", "startup", "functionlist", "methodlist", "class"
407 const unsigned int nums
= sizeof(parts
)/sizeof(char *);
408 unsigned int partnum
;
412 while (isspace(*s
)) s
++;
414 if (strncmp(s
, "begin", 5)!=0)
419 exitfileerror(20, "space after begin expected\n");
420 while (isspace(*s
)) s
++;
422 for (i
= 0, partnum
= 0; partnum
==0 && i
<nums
; i
++)
424 if (strncmp(s
, parts
[i
], strlen(parts
[i
]))==0)
427 s
+= strlen(parts
[i
]);
428 while (isspace(*s
)) s
++;
430 exitfileerror(20, "unexpected character on position %d\n", s
-line
);
434 exitfileerror(20, "unknown start of section\n");
438 readsectionconfig(cfg
, cl
, inclass
);
442 case 2: /* cdefprivate */
444 exitfileerror(20, "cdefprivate section not allowed in class section\n");
445 readsectioncdefprivate(cfg
);
450 exitfileerror(20, "cdef section not allowed in class section\n");
451 readsectioncdef(cfg
);
454 case 4: /* startup */
456 exitfileerror(20, "startup section not allowed in class section\n");
457 readsectionstartup(cfg
);
460 case 5: /* functionlist */
462 exitfileerror(20, "functionlist section not allow in class section\n");
463 readsectionfunctionlist(cfg
);
464 cfg
->intcfg
|= CFG_NOREADREF
;
467 case 6: /* methodlist */
469 exitfileerror(20, "methodlist section when not in a class\n");
470 readsectionmethodlist(cl
);
471 cfg
->intcfg
|= CFG_NOREADREF
;
476 exitfileerror(20, "class section may not be nested\n");
477 readsectionclass(cfg
);
481 else if (strlen(line
)!=0)
482 filewarning("warning line outside section ignored\n");
488 exitfileerror(20, "No config section in conffile\n");
490 /* If no indication was given for generating includes or not
491 decide on module type and if there are functions
493 if(!((cfg
->options
& OPTION_INCLUDES
) || (cfg
->options
& OPTION_NOINCLUDES
)))
495 switch (cfg
->modtype
)
500 cfg
->options
|= OPTION_INCLUDES
;
505 (cfg
->funclist
!= NULL
)
506 || (cfg
->cdeflines
!= NULL
)
507 || strcmp(cfg
->libbasetypeptrextern
, "struct Device *") != 0
508 ) ? OPTION_INCLUDES
: OPTION_NOINCLUDES
;
518 (cfg
->funclist
!= NULL
)
519 || (cfg
->cdeflines
!= NULL
)
520 ) ? OPTION_INCLUDES
: OPTION_NOINCLUDES
;
524 fprintf(stderr
, "Internal error writemakefile: unhandled modtype for includes\n");
530 /* If no indication was given for not generating stubs only generate them if
531 * the module has functions
533 if(!((cfg
->options
& OPTION_STUBS
) || (cfg
->options
& OPTION_NOSTUBS
)))
535 cfg
->options
|= (cfg
->funclist
!= NULL
) ?
536 OPTION_STUBS
: OPTION_NOSTUBS
;
539 /* If no indication was given for generating autoinit code or not
540 decide on module type
542 if(!((cfg
->options
& OPTION_AUTOINIT
) || (cfg
->options
& OPTION_NOAUTOINIT
)))
544 switch (cfg
->modtype
)
548 cfg
->options
|= OPTION_AUTOINIT
;
559 cfg
->options
|= OPTION_NOAUTOINIT
;
563 fprintf(stderr
, "Internal error writemakefile: unhandled modtype for autoinit\n");
569 if (cfg
->modtype
== RESOURCE
)
570 /* Enforce noopenclose for resources */
571 cfg
->options
|= OPTION_NOOPENCLOSE
;
573 /* Enforce using RTF_AUTOINIT for everything except resources */
574 cfg
->options
|= OPTION_RESAUTOINIT
;
579 static void readsectionconfig(struct config
*cfg
, struct classinfo
*cl
, int inclass
)
582 char *line
, *s
, *s2
, *libbasetypeextern
= NULL
;
589 exitfileerror(20, "unexpected end of file in section config\n");
591 if (strncmp(line
, "##", 2)!=0)
593 const char *names
[] =
595 "basename", "libbase", "libbasetype", "libbasetypeextern",
596 "version", "date", "copyright", "libcall", "forcebase", "superclass",
597 "superclass_field", "residentpri", "options", "sysbase_field",
598 "seglist_field", "rootbase_field", "classptr_field", "classptr_var",
599 "classid", "classdatatype", "beginio_func", "abortio_func", "dispatcher",
600 "initpri", "type", "getidfunc"
602 const unsigned int namenums
= sizeof(names
)/sizeof(char *);
603 unsigned int namenum
;
605 for (i
= 0, namenum
= 0; namenum
==0 && i
<namenums
; i
++)
609 strncmp(line
, names
[i
], strlen(names
[i
]))==0
610 && isspace(*(line
+strlen(names
[i
])))
615 exitfileerror(20, "unrecognized configuration option\n");
617 s
= line
+ strlen(names
[namenum
-1]);
619 exitfileerror(20, "space character expected after \"%s\"\n", names
[namenum
-1]);
621 while (isspace(*s
)) s
++;
623 exitfileerror(20, "unexpected end of line\n");
626 while (isspace(*(s2
-1))) s2
--;
631 case 1: /* basename */
633 cfg
->basename
= strdup(s
);
635 cl
->basename
= strdup(s
);
638 case 2: /* libbase */
640 exitfileerror(20, "libbase not valid config option when in a class section\n");
641 cfg
->libbase
= strdup(s
);
644 case 3: /* libbasetype */
646 exitfileerror(20, "libbasetype not valid config option when in a class section\n");
647 cfg
->libbasetype
= strdup(s
);
650 case 4: /* libbasetypeextern */
652 exitfileerror(20, "libbasetype not valid config option when in a class section\n");
653 libbasetypeextern
= strdup(s
);
656 case 5: /* version */
658 exitfileerror(20, "version not valid config option when in a class section\n");
659 if (sscanf(s
, "%u.%u", &cfg
->majorversion
, &cfg
->minorversion
)!=2)
660 exitfileerror(20, "wrong version string \"%s\"\n", s
);
665 exitfileerror(20, "date not valid config option when in a class section\n");
667 if (strptime(s
, "%e.%m.%Y", &date
) == NULL
)
669 exitfileerror(20, "date string has to have d.m.yyyy format\n");
672 cfg
->datestring
= strdup(s
);
675 case 7: /* copyright */
677 exitfileerror(20, "copyright not valid config option when in a class section\n");
678 cfg
->copyright
= strdup(s
);
681 case 8: /* libcall */
682 fprintf(stderr
, "libcall specification is deprecated and ignored\n");
685 case 9: /* forcebase */
687 exitfileerror(20, "forcebase not valid config option when in a class section\n");
688 slist_append(&cfg
->forcelist
, s
);
691 case 10: /* superclass */
693 exitfileerror(20, "superclass specified when not a BOOPSI class\n");
694 cl
->superclass
= strdup(s
);
697 case 11: /* superclass_field */
699 exitfileerror(20, "superclass_field specified when not a BOOPSI class\n");
700 cl
->superclass_field
= strdup(s
);
703 case 12: /* residentpri */
709 count
= sscanf(s
, "%d%c", &cfg
->residentpri
, &dummy
);
711 cfg
->residentpri
< -128 || cfg
->residentpri
> 127
714 exitfileerror(20, "residentpri number format error\n");
718 exitfileerror(20, "residentpri not valid config option when in a class section\n");
721 case 13: /* options */
724 static const char *optionnames
[] =
726 "noautolib", "noexpunge", "noresident", "peropenerbase",
727 "peridbase", "includes", "noincludes", "nostubs",
728 "autoinit", "noautoinit", "resautoinit", "noopenclose"
730 const unsigned int optionnums
= sizeof(optionnames
)/sizeof(char *);
735 for (i
= 0, optionnum
= 0; optionnum
==0 && i
<optionnums
; i
++)
737 if (strncmp(s
, optionnames
[i
], strlen(optionnames
[i
]))==0)
740 s
+= strlen(optionnames
[i
]);
741 while (isspace(*s
)) s
++;
745 exitfileerror(20, "Unrecognized option\n");
749 exitfileerror(20, "Unrecognized option\n");
752 case 1: /* noautolib */
753 cfg
->options
|= OPTION_NOAUTOLIB
;
755 case 2: /* noexpunge */
756 cfg
->options
|= OPTION_NOEXPUNGE
;
758 case 3: /* noresident */
759 cfg
->options
|= OPTION_NORESIDENT
;
762 case 5: /* peridbase */
763 cfg
->options
|= OPTION_DUPPERID
;
765 case 4: /* peropenerbase */
766 if (cfg
->options
& OPTION_DUPBASE
)
767 exitfileerror(20, "Only one option peropenerbase or peridbase allowed\n");
768 cfg
->options
|= OPTION_DUPBASE
;
770 case 6: /* includes */
771 if (cfg
->options
& OPTION_NOINCLUDES
)
772 exitfileerror(20, "option includes and noincludes are incompatible\n");
773 cfg
->options
|= OPTION_INCLUDES
;
775 case 7: /* noincludes */
776 if (cfg
->options
& OPTION_INCLUDES
)
777 exitfileerror(20, "option includes and noincludes are incompatible\n");
778 cfg
->options
|= OPTION_NOINCLUDES
;
780 case 8: /* nostubs */
781 cfg
->options
|= OPTION_NOSTUBS
;
783 case 9: /* autoinit */
784 if (cfg
->options
& OPTION_NOAUTOINIT
)
785 exitfileerror(20, "option autoinit and noautoinit are incompatible\n");
786 cfg
->options
|= OPTION_AUTOINIT
;
788 case 10: /* noautoinit */
789 if (cfg
->options
& OPTION_AUTOINIT
)
790 exitfileerror(20, "option autoinit and noautoinit are incompatible\n");
791 cfg
->options
|= OPTION_NOAUTOINIT
;
793 case 11: /* resautoinit */
794 cfg
->options
|= OPTION_RESAUTOINIT
;
797 cfg
->options
|= OPTION_NOOPENCLOSE
;
800 while (isspace(*s
)) s
++;
805 static const char *optionnames
[] =
809 const unsigned int optionnums
= sizeof(optionnames
)/sizeof(char *);
814 for (i
= 0, optionnum
= 0; optionnum
==0 && i
<optionnums
; i
++)
816 if (strncmp(s
, optionnames
[i
], strlen(optionnames
[i
]))==0)
819 s
+= strlen(optionnames
[i
]);
820 while (isspace(*s
)) s
++;
824 exitfileerror(20, "Unrecognized option\n");
828 exitfileerror(20, "Unrecognized option\n");
831 case 1: /* private */
832 cl
->options
|= COPTION_PRIVATE
;
835 while (isspace(*s
)) s
++;
840 case 14: /* sysbase_field */
842 exitfileerror(20, "sysbase_field not valid config option when in a class section\n");
843 cfg
->sysbase_field
= strdup(s
);
846 case 15: /* seglist_field */
848 exitfileerror(20, "seglist_field not valid config option when in a class section\n");
849 cfg
->seglist_field
= strdup(s
);
852 case 16: /* rootbase_field */
854 exitfileerror(20, "rootbase_field not valid config option when in a class section\n");
855 cfg
->rootbase_field
= strdup(s
);
858 case 17: /* classptr_field */
864 "classptr_field specified when not a BOOPSI class\n"
867 cl
->classptr_field
= strdup(s
);
870 case 18: /* classptr_var */
876 "classptr_var specified when not a BOOPSI class\n"
879 cl
->classptr_var
= strdup(s
);
882 case 19: /* classid */
884 exitfileerror(20, "classid specified when not a BOOPSI class\n");
885 if (cl
->classid
!= NULL
)
886 exitfileerror(20, "classid specified twice\n");
887 cl
->classid
= strdup(s
);
888 if (strcmp(cl
->classid
, "NULL") == 0)
889 cl
->options
|= COPTION_PRIVATE
;
892 case 20: /* classdatatype */
894 exitfileerror(20, "classdatatype specified when not a BOOPSI class\n");
895 cl
->classdatatype
= strdup(s
);
898 case 21: /* beginio_func */
900 exitfileerror(20, "beginio_func not valid config option when in a class section\n");
901 if (cfg
->modtype
!= DEVICE
)
902 exitfileerror(20, "beginio_func specified when not a device\n");
903 cfg
->beginiofunc
= strdup(s
);
906 case 22: /* abortio_func */
908 exitfileerror(20, "abortio_func not valid config option when in a class section\n");
909 if (cfg
->modtype
!= DEVICE
)
910 exitfileerror(20, "abortio_func specified when not a device\n");
911 cfg
->abortiofunc
= strdup(s
);
914 case 23: /* dispatcher */
916 exitfileerror(20, "dispatcher specified when not a BOOPSI class\n");
917 cl
->dispatcher
= strdup(s
);
918 /* function references are not needed when dispatcher is specified */
919 cfg
->intcfg
|= CFG_NOREADREF
;
922 case 24: /* initpri */
928 count
= sscanf(s
, "%d%c", &cl
->initpri
, &dummy
);
930 cl
->initpri
< -128 || cl
->initpri
> 127
933 exitfileerror(20, "initpri number format error\n");
937 exitfileerror(20, "initpri only valid config option for a BOOPSI class\n");
942 exitfileerror(20, "type only valid config option in a class section\n");
943 if (strcmp(s
,"mcc")==0)
945 else if (strcmp(s
,"mui")==0)
947 else if (strcmp(s
,"mcp")==0)
949 else if (strcmp(s
, "image")==0)
950 cl
->classtype
= IMAGE
;
951 else if (strcmp(s
, "gadget")==0)
952 cl
->classtype
= GADGET
;
953 else if (strcmp(s
, "datatype")==0)
954 cl
->classtype
= DATATYPE
;
955 else if (strcmp(s
, "usbclass")==0)
956 cl
->classtype
= USBCLASS
;
957 else if (strcmp(s
, "class")==0)
958 cl
->classtype
= CLASS
;
959 else if (strcmp(s
, "hidd")==0)
960 cl
->classtype
= HIDD
;
963 fprintf(stderr
, "Unknown type \"%s\" specified\n", s
);
967 case 26: /* getidfunc */
968 cfg
->getidfunc
= strdup(s
);
972 else /* Line starts with ## */
975 while (isspace(*s
)) s
++;
976 if (strncmp(s
, "end", 3)!=0)
977 exitfileerror(20, "\"##end config\" expected\n");
981 exitfileerror(20, "\"##end config\" expected\n");
983 while (isspace(*s
)) s
++;
984 if (strncmp(s
, "config", 6)!=0)
985 exitfileerror(20, "\"##end config\" expected\n");
988 while (isspace(*s
)) s
++;
990 exitfileerror(20, "\"##end config\" expected\n");
996 /* When not in a class section fill in default values for fields in cfg */
999 if (cfg
->basename
==NULL
)
1001 cfg
->basename
= strdup(cfg
->modulename
);
1002 *cfg
->basename
= toupper(*cfg
->basename
);
1004 if (cfg
->libbase
==NULL
)
1006 unsigned int len
= strlen(cfg
->basename
)+5;
1007 cfg
->libbase
= malloc(len
);
1008 snprintf(cfg
->libbase
, len
, "%sBase", cfg
->basename
);
1010 if (cfg
->libbasetype
== NULL
&& libbasetypeextern
!= NULL
)
1011 cfg
->libbasetype
= strdup(libbasetypeextern
);
1012 if (cfg
->sysbase_field
!= NULL
&& cfg
->libbasetype
== NULL
)
1013 exitfileerror(20, "sysbase_field specified when no libbasetype is given\n");
1014 if (cfg
->seglist_field
!= NULL
&& cfg
->libbasetype
== NULL
)
1015 exitfileerror(20, "seglist_field specified when no libbasetype is given\n");
1016 /* rootbase_field only allowed when duplicating base */
1017 if (cfg
->rootbase_field
!= NULL
&& !(cfg
->options
& OPTION_DUPBASE
))
1018 exitfileerror(20, "rootbasefield only valid for option peropenerbase or peridbase\n");
1019 if (cfg
->getidfunc
!= NULL
&& !(cfg
->options
& OPTION_DUPPERID
))
1020 exitfileerror(20, "getidfunc only valid for option peridbase\n");
1022 /* Set default date to current date */
1023 if (cfg
->datestring
== NULL
)
1026 time_t now
= time(NULL
);
1027 struct tm
*ltime
= localtime(&now
);
1029 snprintf(tmpbuf
, sizeof(tmpbuf
), "%u.%u.%u",
1030 ltime
->tm_mday
, 1 + ltime
->tm_mon
, 1900 + ltime
->tm_year
);
1032 cfg
->datestring
= strdup(tmpbuf
);
1035 if (cfg
->copyright
== NULL
)
1036 cfg
->copyright
= "";
1038 if ( (cfg
->beginiofunc
!= NULL
&& cfg
->abortiofunc
== NULL
)
1039 || (cfg
->beginiofunc
== NULL
&& cfg
->abortiofunc
!= NULL
)
1041 exitfileerror(20, "please specify both beginio_func and abortio_func\n");
1043 if (libbasetypeextern
==NULL
)
1045 switch (cfg
->modtype
)
1048 cfg
->libbasetypeptrextern
= "struct Device *";
1051 cfg
->libbasetypeptrextern
= "APTR ";
1061 cfg
->libbasetypeptrextern
= "struct Library *";
1064 fprintf(stderr
, "Internal error: Unsupported modtype for libbasetypeptrextern\n");
1070 cfg
->libbasetypeptrextern
= malloc(strlen(libbasetypeextern
)+3);
1071 strcpy(cfg
->libbasetypeptrextern
, libbasetypeextern
);
1072 strcat(cfg
->libbasetypeptrextern
, " *");
1073 free(libbasetypeextern
);
1077 /* When class was given too fill in some defaults when not specified */
1080 if (cl
->classtype
== UNSPECIFIED
)
1081 cl
->classtype
= CLASS
;
1083 if (cl
->basename
== NULL
)
1086 cl
->basename
= cfg
->basename
;
1088 exitfileerror(20, "basename has to be specified in the config section inside of a class section\n");
1091 /* MUI classes are always private */
1092 if (cl
->classtype
== MUI
|| cl
->classtype
== MCC
|| cl
->classtype
== MCP
)
1093 cl
->options
|= COPTION_PRIVATE
;
1095 if (cl
->classid
== NULL
1096 && (cl
->classtype
!= MUI
&& cl
->classtype
!= MCC
&& cl
->classtype
!= MCP
)
1099 if (cl
->classtype
== HIDD
)
1101 cl
->options
&= !COPTION_PRIVATE
;
1103 else if (cl
->options
& COPTION_PRIVATE
)
1105 cl
->classid
= "NULL";
1111 if (cl
->classtype
== GADGET
|| cl
->classtype
== IMAGE
|| cl
->classtype
== CLASS
|| cl
->classtype
== USBCLASS
)
1113 sprintf(s
, "\"%sclass\"", inclass
? cl
->basename
: cfg
->modulename
);
1115 else if (cl
->classtype
== DATATYPE
)
1117 sprintf(s
, "\"%s.datatype\"", inclass
? cl
->basename
: cfg
->modulename
);
1119 cl
->classid
= strdup(s
);
1123 /* Only specify superclass or superclass_field */
1124 if (cl
->superclass
!= NULL
&& cl
->superclass_field
!= NULL
)
1125 exitfileerror(20, "Only specify one of superclass or superclass_field in config section\n");
1127 /* Give default value to superclass if it is not specified */
1128 if (cl
->superclass
== NULL
&& cl
->superclass
== NULL
)
1130 switch (cl
->classtype
)
1134 cl
->superclass
= "MUIC_Area";
1137 cl
->superclass
= "MUIC_Mccprefs";
1140 cl
->superclass
= "IMAGECLASS";
1143 cl
->superclass
= "GADGETCLASS";
1146 cl
->superclass
= "DATATYPESCLASS";
1149 cl
->superclass
= "ROOTCLASS";
1152 cl
->superclass
= "CLID_Root";
1155 exitfileerror(20, "Internal error: unhandled classtype in readsectionconfig\n");
1162 static void readsectioncdef(struct config
*cfg
)
1171 exitfileerror(20, "unexptected end of file in section cdef\n");
1173 if (strncmp(line
, "##", 2)!=0)
1175 slist_append(&cfg
->cdeflines
, line
);
1180 while (isspace(*s
)) s
++;
1181 if (strncmp(s
, "end", 3)!=0)
1182 exitfileerror(20, "\"##end cdef\" expected\n");
1185 while (isspace(*s
)) s
++;
1186 if (strncmp(s
, "cdef", 4)!=0)
1187 exitfileerror(20, "\"##end cdef\" expected\n");
1190 while (isspace(*s
)) s
++;
1192 exitfileerror(20, "unexpected character at position %d\n");
1199 static void readsectioncdefprivate(struct config
*cfg
)
1208 exitfileerror(20, "unexptected end of file in section cdef\n");
1210 if (strncmp(line
, "##", 2)!=0)
1212 slist_append(&cfg
->cdefprivatelines
, line
);
1217 while (isspace(*s
)) s
++;
1218 if (strncmp(s
, "end", 3)!=0)
1219 exitfileerror(20, "\"##end cdefprivate\" expected\n");
1222 while (isspace(*s
)) s
++;
1223 if (strncmp(s
, "cdefprivate", 11)!=0)
1224 exitfileerror(20, "\"##end cdefprivate\" expected\n");
1227 while (isspace(*s
)) s
++;
1229 exitfileerror(20, "unexpected character at position %d\n");
1236 static void readsectionstartup(struct config
*cfg
)
1245 exitfileerror(20, "unexptected end of file in section startup\n");
1247 if (strncmp(line
, "##", 2)!=0)
1249 slist_append(&cfg
->startuplines
, line
);
1254 while (isspace(*s
)) s
++;
1255 if (strncmp(s
, "end", 3)!=0)
1256 exitfileerror(20, "\"##end startup\" expected\n");
1259 while (isspace(*s
)) s
++;
1260 if (strncmp(s
, "startup", 7)!=0)
1261 exitfileerror(20, "\"##end startup\" expected\n");
1264 while (isspace(*s
)) s
++;
1266 exitfileerror(20, "unexpected character at position %d\n");
1273 static void readsectionfunctionlist(struct config
*cfg
)
1276 char *line
, *s
, *s2
;
1277 unsigned int lvo
= cfg
->firstlvo
;
1278 struct functionhead
**funclistptr
= &cfg
->funclist
;
1280 if (cfg
->basename
==NULL
)
1281 exitfileerror(20, "section functionlist has to come after section config\n");
1287 exitfileerror(20, "unexptected EOF in functionlist section\n");
1288 if (strlen(line
)==0)
1290 if (*funclistptr
!= NULL
)
1291 funclistptr
= &((*funclistptr
)->next
);
1294 else if (isspace(*line
))
1297 while (isspace(*s
)) s
++;
1300 if (*funclistptr
!= NULL
)
1301 funclistptr
= &((*funclistptr
)->next
);
1305 exitfileerror(20, "no space allowed before functionname\n");
1307 else if (strncmp(line
, "##", 2)==0)
1310 while (isspace(*s
)) s
++;
1311 if (strncmp(s
, "end", 3)!=0)
1312 exitfileerror(20, "\"##end functionlist\" expected\n");
1315 while (isspace(*s
)) s
++;
1316 if (strncmp(s
, "functionlist", 12)!=0)
1317 exitfileerror(20, "\"##end functionlist\" expected\n");
1320 while (isspace(*s
)) s
++;
1322 exitfileerror(20, "unexpected character on position %d\n", s
-line
);
1326 else if (*line
=='.')
1329 if (strncmp(s
, "skip", 4)==0)
1335 exitfileerror(20, "syntax is '.skip n'\n");
1337 n
=strtol(s
, &s2
, 10);
1339 exitfileerror(20, "positive number expected\n");
1341 while (isspace(*s2
)) s2
++;
1343 exitfileerror(20, "syntax is '.skip n'\n");
1344 if (*funclistptr
!= NULL
)
1345 funclistptr
= &((*funclistptr
)->next
);
1348 else if (strncmp(s
, "alias", 5)==0)
1353 exitfileerror(20, "syntax is '.alias name'\n");
1355 while (isspace(*s
)) s
++;
1356 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1357 exitfileerror(20, "syntax is '.alias name'\n");
1361 while (isalnum(*s
) || *s
== '_') s
++;
1368 } while (isspace(*s
));
1372 exitfileerror(20, "syntax is '.alias name'\n");
1374 if (*funclistptr
== NULL
)
1375 exitfileerror(20, ".alias has to come after a function declaration\n");
1377 slist_append(&(*funclistptr
)->aliases
, s2
);
1378 cfg
->intcfg
|= CFG_GENASTUBS
;
1380 else if (strncmp(s
, "function", 8) == 0)
1385 exitfileerror(20, "Syntax error\n");
1387 while (isspace(*s
)) s
++;
1388 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1389 exitfileerror(20, "syntax is '.function name'\n");
1393 while (isalnum(*s
) || *s
== '_') s
++;
1400 } while (isspace(*s
));
1404 exitfileerror(20, "syntax is '.function name'\n");
1406 if (*funclistptr
== NULL
)
1407 exitfileerror(20, ".function has to come after a function declaration\n");
1409 funcsetinternalname(*funclistptr
, s2
);
1411 else if (strncmp(s
, "cfunction", 9)==0)
1413 if (*funclistptr
== NULL
)
1414 exitfileerror(20, ".cfunction has to come after a function declaration\n");
1416 (*funclistptr
)->libcall
= REGISTER
;
1418 else if (strncmp(s
, "private", 7)==0)
1420 if (*funclistptr
== NULL
)
1421 exitfileerror(20, ".private has to come after a function declaration\n");
1423 (*funclistptr
)->priv
= 1;
1425 else if (strncmp(s
, "novararg", 8)==0)
1427 if (*funclistptr
== NULL
)
1428 exitfileerror(20, ".novararg has to come after a function declaration\n");
1430 (*funclistptr
)->novararg
= 1;
1433 exitfileerror(20, "Syntax error");
1435 else if (*line
!='#') /* Ignore line that is a comment, e.g. that starts with a # */
1437 /* The line is a function prototype. It can have two syntax
1438 * type funcname(argproto1, argproto2, ...)
1439 * type funcname(argproto1, argproto2, ...) (reg1, reg2, ...)
1440 * The former is for C type function argument passing, the latter for
1441 * register argument passing.
1443 char c
, *args
[64], *regs
[64], *funcname
;
1444 int len
, argcount
= 0, regcount
= 0, brcount
= 0;
1446 /* Parse 'type functionname' at the beginning of the line */
1447 s
= strchr(line
, '(');
1449 exitfileerror(20, "( expected at position %d\n", strlen(line
) + 1);
1452 while (isspace(*(s2
-1)))
1456 while (s2
> line
&& !isspace(*(s2
-1)) && !(*(s2
-1) == '*'))
1460 exitfileerror(20, "No type specifier before function name\n");
1462 if (*funclistptr
!= NULL
)
1463 funclistptr
= &((*funclistptr
)->next
);
1464 *funclistptr
= newfunctionhead(s2
, STACK
);
1466 while (isspace(*(s2
-1)))
1469 (*funclistptr
)->type
= strdup(line
);
1470 (*funclistptr
)->lvo
= lvo
;
1473 /* Parse function prototype */
1490 && !(brcount
== 0 && (*s
== ',' || *s
== ')'))
1500 exitfileerror(20, "Unexected ')' at position %d\n", s
-line
+1);
1507 exitfileerror(20, "'(' without ')'");
1510 while (isspace(*(s2
-1)))
1514 if (!(s2
> args
[argcount
- 1]))
1515 exitfileerror(20, "Syntax error in function prototype\n");
1521 while (*s
!= '\0' && isspace(*s
))
1526 /* Parse registers specifications if available otherwise this prototype for C type argument passing */
1528 /* There may be no register specified with () so be sure then c is == ')' */
1543 if (memchr("AD",s
[0],2)!=NULL
&& memchr("01234567",s
[1],8)!=NULL
)
1551 if (strchr(regs
[0], '/') == NULL
)
1552 exitfileerror(20, "Either all arguments has to in two registers or none\n");
1556 if (s
[0] == s
[-3] && s
[1] == s
[-2] + 1)
1563 "wrong register specification \"%s\" for argument %u\n",
1564 regs
[regcount
-1], regcount
1568 exitfileerror(20, "maximum two arguments passed in two registers allowed\n");
1574 "wrong register \"%s\" for argument %u\n",
1575 regs
[regcount
-1], regcount
1584 exitfileerror(20, "'(' without ')'\n");
1585 if (c
!= ',' && c
!= ')')
1586 exitfileerror(20, "',' or ')' expected at position %d\n", s
-line
+1);
1592 while (isspace(*s
)) s
++;
1594 exitfileerror(20, "wrong char '%c' at position %d\n", *s
, (int)(s
-line
) + 1);
1596 if (argcount
!= regcount
)
1597 exitfileerror(20, "Number of arguments (%d) and registers (%d) mismatch\n",
1601 (*funclistptr
)->libcall
= REGISTERMACRO
;
1602 for (i
= 0; i
< argcount
; i
++)
1603 funcaddarg(*funclistptr
, args
[i
], regs
[i
]);
1605 else if (*s
== '\0')
1606 { /* No registers specified */
1607 for (i
= 0; i
< argcount
; i
++)
1608 funcaddarg(*funclistptr
, args
[i
], NULL
);
1609 cfg
->intcfg
|= CFG_GENASTUBS
;
1612 exitfileerror(20, "wrong char '%c' at position %d\n", *s
, (int)(s
-line
) + 1);
1617 static void readsectionmethodlist(struct classinfo
*cl
)
1620 char *line
, *s
, *s2
;
1621 struct functionhead
**methlistptr
= &cl
->methlist
;
1622 struct stringlist
*interface
= NULL
;
1624 if (cl
->basename
==NULL
)
1625 exitfileerror(20, "section methodlist has to come after section config\n");
1631 exitfileerror(20, "unexptected EOF in methodlist section\n");
1633 /* Ignore empty lines or lines that qre a comment, e.g. that starts with a # */
1634 if (strlen(line
)==0 || (line
[0] == '#' && line
[1] != '#'))
1638 exitfileerror(20, "No space allowed at start of the line\n");
1640 if (strncmp(line
, "##", 2)==0) /* Is this the end ? */
1643 while (isspace(*s
)) s
++;
1644 if (strncmp(s
, "end", 3)!=0)
1645 exitfileerror(20, "\"##end methodlist\" expected\n");
1648 while (isspace(*s
)) s
++;
1649 if (strncmp(s
, "methodlist", 10)!=0)
1650 exitfileerror(20, "\"##end methodlist\" expected\n");
1653 while (isspace(*s
)) s
++;
1655 exitfileerror(20, "unexpected character on position %d\n", s
-line
);
1665 if (strncmp(s
, "alias", 5)==0)
1670 exitfileerror(20, "syntax is '.alias name'\n");
1672 while (isspace(*s
)) s
++;
1673 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1674 exitfileerror(20, "syntax is '.alias name'\n");
1678 while (isalnum(*s
) || *s
== '_') s
++;
1685 } while (isspace(*s
));
1689 exitfileerror(20, "syntax is '.alias name'\n");
1691 if (*methlistptr
== NULL
)
1692 exitfileerror(20, ".alias has to come after a function declaration\n");
1694 slist_append(&(*methlistptr
)->aliases
, s2
);
1696 else if (strncmp(s
, "function", 8) == 0)
1701 exitfileerror(20, "Syntax error\n");
1703 while (isspace(*s
)) s
++;
1704 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1705 exitfileerror(20, "syntax is '.function name'\n");
1709 while (isalnum(*s
) || *s
== '_') s
++;
1716 } while (isspace(*s
));
1720 exitfileerror(20, "syntax is '.function name'\n");
1722 if (*methlistptr
== NULL
)
1723 exitfileerror(20, ".function has to come after a function declaration\n");
1725 funcsetinternalname(*methlistptr
, s2
);
1727 else if (strncmp(s
, "interface", 9) == 0)
1729 if (cl
->classtype
!= HIDD
)
1730 exitfileerror(20, "interface only valid for a HIDD\n");
1735 exitfileerror(20, "Syntax error\n");
1737 while (isspace(*s
)) s
++;
1738 if (*s
== '\0' || !isalpha(*s
))
1739 exitfileerror(20, "syntax is '.interface name'\n");
1743 while (isalnum(*s
) || *s
== '_') s
++;
1750 } while (isspace(*s
));
1754 exitfileerror(20, "syntax is '.interface name'\n");
1756 interface
= slist_append(&cl
->interfaces
, s2
);
1759 exitfileerror(20, "Syntax error");
1761 else if (isalpha(*line
))
1765 for (s
= line
+ 1; isalnum(*s
) || *s
== '_'; s
++)
1768 if (cl
->classtype
== HIDD
&& interface
== NULL
)
1769 exitfileerror(20, "For a HIDD the first method has to come after an .interface line\n");
1772 exitfileerror(20, "Only letters, digits and an underscore allowed in a methodname\n");
1774 if (*methlistptr
!= NULL
)
1775 methlistptr
= &((*methlistptr
)->next
);
1776 if (cl
->classtype
!= HIDD
)
1778 if (snprintf(stmp
, 256, "%s__%s", cl
->basename
, line
) >= 256)
1779 exitfileerror(20, "Method name too large\n");
1781 *methlistptr
= newfunctionhead(stmp
, STACK
);
1782 (*methlistptr
)->type
= "IPTR";
1783 funcaddarg(*methlistptr
, "Class *cl", NULL
);
1784 funcaddarg(*methlistptr
, "Object *o", NULL
);
1785 funcaddarg(*methlistptr
, "Msg msg", NULL
);
1789 if (snprintf(stmp
, 256, "%s__%s__%s", cl
->basename
, interface
->s
, line
) >= 256)
1790 exitfileerror(20, "Method name too large\n");
1792 *methlistptr
= newfunctionhead(stmp
, STACK
);
1793 (*methlistptr
)->type
= "IPTR";
1794 funcaddarg(*methlistptr
, "OOP_Class *cl", NULL
);
1795 funcaddarg(*methlistptr
, "OOP_Object *o", NULL
);
1796 funcaddarg(*methlistptr
, "OOP_Msg msg", NULL
);
1797 (*methlistptr
)->interface
= interface
;
1798 if (snprintf(stmp
, 256, "mo%s_%s", interface
->s
, line
) >= 256)
1799 exitfileerror(20, "Method name too large\n");
1800 (*methlistptr
)->method
= strdup(stmp
);
1802 slist_append(&(*methlistptr
)->aliases
, line
);
1805 exitfileerror(20, "Methodname has to begin with a letter\n");
1810 readsectionclass(struct config
*cfg
)
1813 struct classinfo
*cl
;
1816 s
= readsections(cfg
, cl
, 1);
1818 exitfileerror(20, "Unexpected end of file\n");
1820 if (strncmp(s
, "##", 2) != 0)
1821 exitfileerror(20, "'##end class' expected\n");
1824 while (isspace(*s
)) s
++;
1826 if (strncmp(s
, "end", 3) != 0)
1827 exitfileerror(20, "'##end class' expected\n");
1831 exitfileerror(20, "'##end class' expected\n");
1832 while (isspace(*s
)) s
++;
1834 if (strncmp(s
, "class", 5) != 0)
1835 exitfileerror(20, "'##end class' expected\n");
1838 while (isspace(*s
)) s
++;
1840 exitfileerror(20, "'##end class' expected\n");
1843 static struct classinfo
*newclass(struct config
*cfg
)
1845 struct classinfo
*cl
, *classlistit
;
1847 cl
= malloc(sizeof(struct classinfo
));
1850 fprintf(stderr
, "Out of memory\n");
1853 memset(cl
, 0, sizeof(struct classinfo
));
1855 /* By default the classes are initialized with a priority of 1 so they
1856 * are initialized before any user added initialization with priority 1
1860 if (cfg
->classlist
== NULL
)
1861 cfg
->classlist
= cl
;
1866 classlistit
= cfg
->classlist
;
1867 classlistit
->next
!= NULL
;
1868 classlistit
= classlistit
->next
1871 classlistit
->next
= cl
;