2 Copyright © 1995-2008, The AROS Development Team. All rights reserved.
5 Code to parse the command line options and the module config file for
15 #include "functionhead.h"
18 static char banner
[256] = "\0";
22 getBanner(struct config
* config
)
24 if (banner
[0] == '\0')
26 snprintf (banner
, 255,
28 " *** Automatically generated from '%s'. Edits will be lost. ***\n"
29 " Copyright © 1995-2008, The AROS Development Team. All rights reserved.\n"
30 "*/\n", config
->conffile
37 const static char usage
[] =
39 "Usage: genmodule [-c conffile] [-s suffix] [-d gendir] [-r reffile]\n"
40 " {writefiles|writemakefile|writeincludes|writedummy|writelibdefs|writefunclist} modname modtype\n"
43 static void readconfig(struct config
*);
44 static struct classinfo
*newclass(struct config
*);
46 /* the method prefices for the supported classes */
47 static const char *muimprefix
[] =
53 static const char *gadgetmprefix
[] =
60 static const char *dtmprefix
[] =
69 /* Create a config struct. Initialize with the values from the programs command
70 * line arguments and the contents of the modules .conf file
72 struct config
*initconfig(int argc
, char **argv
)
75 char *s
, **argvit
= argv
+ 1;
78 cfg
= malloc(sizeof(struct config
));
81 fprintf(stderr
, "Out of memory\n");
85 memset(cfg
, 0, sizeof(struct config
));
87 while ((c
= getopt(argc
, argv
, ":c:s:d:r:")) != -1)
90 if (c
== ':' || *optarg
== '-')
92 fprintf(stderr
, "Option -%c needs an argument\n",c
);
99 cfg
->conffile
= optarg
;
102 cfg
->suffix
= optarg
;
106 /* Remove / at end if present */
107 if ((optarg
)[strlen(*argvit
)-1]=='/') (optarg
)[strlen(optarg
)-1]='\0';
108 cfg
->gendir
= optarg
;
111 cfg
->reffile
= optarg
;
114 fprintf(stderr
, "Internal error: Unhandled option\n");
119 if (optind
+ 3 != argc
)
121 fprintf(stderr
, "Wrong number of arguments.\n%s", usage
);
125 if (strcmp(argv
[optind
], "writefiles") == 0)
127 cfg
->command
= FILES
;
129 else if (strcmp(argv
[optind
], "writemakefile") == 0)
131 cfg
->command
= MAKEFILE
;
133 else if (strcmp(argv
[optind
], "writeincludes") == 0)
135 cfg
->command
= INCLUDES
;
137 else if (strcmp(argv
[optind
], "writelibdefs") == 0)
139 cfg
->command
= LIBDEFS
;
141 else if (strcmp(argv
[optind
], "writedummy") == 0)
143 cfg
->command
= DUMMY
;
145 else if (strcmp(argv
[optind
], "writefunclist") == 0)
147 cfg
->command
= WRITEFUNCLIST
;
151 fprintf(stderr
, "Unrecognized argument \"%s\"\n%s", argv
[optind
], usage
);
155 cfg
->modulename
= argv
[optind
+1];
156 cfg
->modulenameupper
= strdup(cfg
->modulename
);
157 for (s
=cfg
->modulenameupper
; *s
!='\0'; *s
= toupper(*s
), s
++)
160 if (strcmp(argv
[optind
+2],"library")==0)
162 cfg
->modtype
= LIBRARY
;
163 cfg
->intcfg
|= CFG_GENLINKLIB
;
164 cfg
->moddir
= "Libs";
166 else if (strcmp(argv
[optind
+2],"mcc")==0)
169 cfg
->moddir
= "Classes/Zune";
171 else if (strcmp(argv
[optind
+2],"mui")==0)
174 cfg
->moddir
= "Classes/Zune";
176 else if (strcmp(argv
[optind
+2],"mcp")==0)
179 cfg
->moddir
= "Classes/Zune";
181 else if (strcmp(argv
[optind
+2], "device")==0)
183 cfg
->modtype
= DEVICE
;
184 cfg
->intcfg
|= CFG_GENLINKLIB
;
185 cfg
->moddir
= "Devs";
187 else if (strcmp(argv
[optind
+2], "resource")==0)
189 cfg
->modtype
= RESOURCE
;
190 cfg
->intcfg
|= CFG_GENLINKLIB
;
191 cfg
->moddir
= "Devs";
193 else if (strcmp(argv
[optind
+2], "gadget")==0)
195 cfg
->modtype
= GADGET
;
196 cfg
->moddir
= "Classes/Gadgets";
198 else if (strcmp(argv
[optind
+2], "datatype")==0)
200 cfg
->modtype
= DATATYPE
;
201 cfg
->moddir
= "Classes/Datatypes";
203 else if (strcmp(argv
[optind
+2], "hidd")==0)
206 cfg
->moddir
= "Devs/Drivers";
210 fprintf(stderr
, "Unknown modtype \"%s\" specified for second argument\n", argv
[2]);
215 cfg
->suffix
= argv
[optind
+2];
219 /* Fill fields with default value if not specified on the command line */
223 if (cfg
->conffile
== NULL
)
225 snprintf(tmpbuf
, sizeof(tmpbuf
), "%s.conf", cfg
->modulename
);
226 cfg
->conffile
= strdup(tmpbuf
);
229 if (cfg
->gendir
== NULL
)
232 if (cfg
->command
!= FILES
&& cfg
->command
!= INCLUDES
&& cfg
->command
!= WRITEFUNCLIST
)
234 if (cfg
->reffile
!= NULL
)
235 fprintf(stderr
, "WARNING ! Option -r ingored for %s\n", argv
[optind
]);
237 else if (cfg
->command
== FILES
&& cfg
->reffile
== NULL
)
239 snprintf(tmpbuf
, sizeof(tmpbuf
), "%s.ref", cfg
->modulename
);
240 cfg
->reffile
= strdup(tmpbuf
);
246 /* For a device add the functions given in beginiofunc and abortiofunc to the functionlist
247 * if they are provided
249 if (cfg
->beginiofunc
!= NULL
)
251 struct functionhead
*funchead
;
253 cfg
->intcfg
|= CFG_NOREADREF
;
255 /* Add beginio_func to the list of functions */
256 funchead
= newfunctionhead(cfg
->beginiofunc
, REGISTERMACRO
);
257 funchead
->type
= strdup("void");
259 funcaddarg(funchead
, "struct IORequest *ioreq", "A1");
261 funchead
->next
= cfg
->funclist
;
262 cfg
->funclist
= funchead
;
264 /* Add abortio_func to the list of functions */
265 funchead
= newfunctionhead(cfg
->abortiofunc
, REGISTERMACRO
);
266 funchead
->type
= strdup("LONG");
268 funcaddarg(funchead
, "struct IORequest *ioreq", "A1");
270 funchead
->next
= cfg
->funclist
->next
;
271 cfg
->funclist
->next
= funchead
;
273 else if (cfg
->modtype
== DEVICE
&& cfg
->intcfg
& CFG_NOREADREF
)
278 "beginio_func and abortio_func missing for a device with a non empty function list\n"
286 /* Functions to read configuration from the configuration file */
288 #include "fileread.h"
290 static char *readsections(struct config
*, struct classinfo
*, int);
291 static void readsectionconfig(struct config
*, struct classinfo
*, int);
292 static void readsectioncdef(struct config
*);
293 static void readsectioncdefprivate(struct config
*);
294 static void readsectionfunctionlist(struct config
*);
295 static void readsectionmethodlist(struct classinfo
*);
296 static void readsectionclass(struct config
*);
298 static void readconfig(struct config
*cfg
)
300 struct classinfo
*mainclass
= NULL
;
302 /* Create a classinfo structure if this module is a class */
303 switch (cfg
->modtype
)
316 mainclass
= newclass(cfg
);
317 mainclass
->classtype
= cfg
->modtype
;
321 fprintf(stderr
, "Internal error: unsupported modtype for classinfo creation\n");
325 switch (cfg
->modtype
)
337 mainclass
->boopsimprefix
= muimprefix
;
344 mainclass
->boopsimprefix
= gadgetmprefix
;
348 mainclass
->boopsimprefix
= dtmprefix
;
352 /* FIXME: need boopsimprefix ? */
355 fprintf(stderr
, "Internal error: unsupported modtype for firstlvo\n");
359 if (!fileopen(cfg
->conffile
))
361 fprintf(stderr
, "In readconfig: Could not open %s\n", cfg
->conffile
);
365 /* Read all sections and see that we are at the end of the file */
366 if (readsections(cfg
, mainclass
, 0) != NULL
)
367 exitfileerror(20, "Syntax error");
372 /* readsections will scan through all the sections in the config file.
374 * struct config *cfg: The module config data which may be updated by
375 * the information in the sections
376 * struct classinfo *cl: The classdata to be filled with data from the sections.
377 * This may be NULL if this is the main part of the configuration file and the
378 * type of the module is not a class
379 * int inclass: Boolean to indicate if we are in a class part. If not we are in the main
380 * part of the config file.
382 static char *readsections(struct config
*cfg
, struct classinfo
*cl
, int inclass
)
386 while ((line
=readline())!=NULL
)
388 if (strncmp(line
, "##", 2)==0)
390 static char *parts
[] =
392 "config", "cdefprivate", "cdef", "functionlist", "methodlist", "class"
394 const unsigned int nums
= sizeof(parts
)/sizeof(char *);
395 unsigned int partnum
;
399 while (isspace(*s
)) s
++;
401 if (strncmp(s
, "begin", 5)!=0)
406 exitfileerror(20, "space after begin expected\n");
407 while (isspace(*s
)) s
++;
409 for (i
= 0, partnum
= 0; partnum
==0 && i
<nums
; i
++)
411 if (strncmp(s
, parts
[i
], strlen(parts
[i
]))==0)
414 s
+= strlen(parts
[i
]);
415 while (isspace(*s
)) s
++;
417 exitfileerror(20, "unexpected character on position %d\n", s
-line
);
421 exitfileerror(20, "unknown start of section\n");
425 readsectionconfig(cfg
, cl
, inclass
);
428 case 2: /* cdefprivate */
430 exitfileerror(20, "cdefprivate section not allowed in class section\n");
431 readsectioncdefprivate(cfg
);
436 exitfileerror(20, "cdef section not allowed in class section\n");
437 readsectioncdef(cfg
);
440 case 4: /* functionlist */
442 exitfileerror(20, "functionlist section not allow in class section\n");
443 readsectionfunctionlist(cfg
);
444 cfg
->intcfg
|= CFG_NOREADREF
;
447 case 5: /* methodlist */
449 exitfileerror(20, "methodlist section when not in a class\n");
450 readsectionmethodlist(cl
);
451 cfg
->intcfg
|= CFG_NOREADREF
;
456 exitfileerror(20, "class section may not be nested\n");
457 readsectionclass(cfg
);
461 else if (strlen(line
)!=0)
462 filewarning("warning line outside section ignored\n");
468 static void readsectionconfig(struct config
*cfg
, struct classinfo
*cl
, int inclass
)
471 char *line
, *s
, *s2
, *libbasetypeextern
= NULL
;
477 exitfileerror(20, "unexpected end of file in section config\n");
479 if (strncmp(line
, "##", 2)!=0)
481 const char *names
[] =
483 "basename", "libbase", "libbasetype", "libbasetypeextern",
484 "version", "date", "copyright", "libcall", "forcebase", "superclass",
485 "superclass_field", "residentpri", "options", "sysbase_field",
486 "seglist_field", "rootbase_field", "classptr_field", "classptr_var",
487 "classid", "classdatatype", "beginio_func", "abortio_func", "dispatcher",
490 const unsigned int namenums
= sizeof(names
)/sizeof(char *);
491 unsigned int namenum
;
493 for (i
= 0, namenum
= 0; namenum
==0 && i
<namenums
; i
++)
497 strncmp(line
, names
[i
], strlen(names
[i
]))==0
498 && isspace(*(line
+strlen(names
[i
])))
503 exitfileerror(20, "unrecognized configuration option\n");
505 s
= line
+ strlen(names
[namenum
-1]);
507 exitfileerror(20, "space character expected after \"%s\"\n", names
[namenum
-1]);
509 while (isspace(*s
)) s
++;
511 exitfileerror(20, "unexpected end of line\n");
514 while (isspace(*(s2
-1))) s2
--;
519 case 1: /* basename */
521 cfg
->basename
= strdup(s
);
523 cl
->basename
= strdup(s
);
526 case 2: /* libbase */
528 exitfileerror(20, "libbase not valid config option when in a class section\n");
529 cfg
->libbase
= strdup(s
);
532 case 3: /* libbasetype */
534 exitfileerror(20, "libbasetype not valid config option when in a class section\n");
535 cfg
->libbasetype
= strdup(s
);
538 case 4: /* libbasetypeextern */
540 exitfileerror(20, "libbasetype not valid config option when in a class section\n");
541 libbasetypeextern
= strdup(s
);
544 case 5: /* version */
546 exitfileerror(20, "version not valid config option when in a class section\n");
547 if (sscanf(s
, "%u.%u", &cfg
->majorversion
, &cfg
->minorversion
)!=2)
548 exitfileerror(20, "wrong version string \"%s\"\n", s
);
553 exitfileerror(20, "date not valid config option when in a class section\n");
554 if (!(strlen(s
)==10 && isdigit(s
[0]) && isdigit(s
[1]) &&
555 s
[2]=='.' && isdigit(s
[3]) && isdigit(s
[4]) &&
556 s
[5]=='.' && isdigit(s
[6]) && isdigit(s
[7]) &&
557 isdigit(s
[8]) && isdigit(s
[9])
561 exitfileerror(20, "date string has have dd.mm.yyyy format\n");
563 cfg
->datestring
= strdup(s
);
566 case 7: /* copyright */
568 exitfileerror(20, "copyright not valid config option when in a class section\n");
569 cfg
->copyright
= strdup(s
);
572 case 8: /* libcall */
573 fprintf(stderr
, "libcall specification is deprecated and ignored\n");
576 case 9: /* forcebase */
578 exitfileerror(20, "forcebase not valid config option when in a class section\n");
579 slist_append(&cfg
->forcelist
, s
);
582 case 10: /* superclass */
584 exitfileerror(20, "superclass specified when not a BOOPSI class\n");
585 cl
->superclass
= strdup(s
);
588 case 11: /* superclass_field */
590 exitfileerror(20, "superclass_field specified when not a BOOPSI class\n");
591 cl
->superclass_field
= strdup(s
);
594 case 12: /* residentpri */
600 count
= sscanf(s
, "%d%c", &cfg
->residentpri
, &dummy
);
602 cfg
->residentpri
< -128 || cfg
->residentpri
> 127
605 exitfileerror(20, "residentpri number format error\n");
609 exitfileerror(20, "residentpri not valid config option when in a class section\n");
612 case 13: /* options */
615 static const char *optionnames
[] =
617 "noautolib", "noexpunge", "noresident", "peropenerbase"
619 const unsigned int optionnums
= sizeof(optionnames
)/sizeof(char *);
624 for (i
= 0, optionnum
= 0; optionnum
==0 && i
<optionnums
; i
++)
626 if (strncmp(s
, optionnames
[i
], strlen(optionnames
[i
]))==0)
629 s
+= strlen(optionnames
[i
]);
630 while (isspace(*s
)) s
++;
634 exitfileerror(20, "Unrecognized option\n");
638 exitfileerror(20, "Unrecognized option\n");
641 case 1: /* noautolib */
642 cfg
->options
|= OPTION_NOAUTOLIB
;
644 case 2: /* noexpunge */
645 cfg
->options
|= OPTION_NOEXPUNGE
;
647 case 3: /* noresident */
648 cfg
->options
|= OPTION_NORESIDENT
;
651 case 4: /* peropenerbase */
652 cfg
->options
|= OPTION_DUPBASE
;
655 while (isspace(*s
)) s
++;
660 static const char *optionnames
[] =
664 const unsigned int optionnums
= sizeof(optionnames
)/sizeof(char *);
669 for (i
= 0, optionnum
= 0; optionnum
==0 && i
<optionnums
; i
++)
671 if (strncmp(s
, optionnames
[i
], strlen(optionnames
[i
]))==0)
674 s
+= strlen(optionnames
[i
]);
675 while (isspace(*s
)) s
++;
679 exitfileerror(20, "Unrecognized option\n");
683 exitfileerror(20, "Unrecognized option\n");
686 case 1: /* private */
687 cl
->options
|= COPTION_PRIVATE
;
690 while (isspace(*s
)) s
++;
695 case 14: /* sysbase_field */
697 exitfileerror(20, "sysbase_field not valid config option when in a class section\n");
698 cfg
->sysbase_field
= strdup(s
);
701 case 15: /* seglist_field */
703 exitfileerror(20, "seglist_field not valid config option when in a class section\n");
704 cfg
->seglist_field
= strdup(s
);
707 case 16: /* rootbase_field */
709 exitfileerror(20, "rootbase_field not valid config option when in a class section\n");
710 cfg
->rootbase_field
= strdup(s
);
713 case 17: /* classptr_field */
719 "classptr_field specified when not a BOOPSI class\n"
722 cl
->classptr_field
= strdup(s
);
725 case 18: /* classptr_var */
731 "classptr_var specified when not a BOOPSI class\n"
734 cl
->classptr_var
= strdup(s
);
737 case 19: /* classid */
739 exitfileerror(20, "classid specified when not a BOOPSI class\n");
740 if (cl
->classid
!= NULL
)
741 exitfileerror(20, "classid specified twice\n");
742 cl
->classid
= strdup(s
);
743 if (strcmp(cl
->classid
, "NULL") == 0)
744 cl
->options
|= COPTION_PRIVATE
;
747 case 20: /* classdatatype */
749 exitfileerror(20, "classdatatype specified when not a BOOPSI class\n");
750 cl
->classdatatype
= strdup(s
);
753 case 21: /* beginio_func */
755 exitfileerror(20, "beginio_func not valid config option when in a class section\n");
756 if (cfg
->modtype
!= DEVICE
)
757 exitfileerror(20, "beginio_func specified when not a device\n");
758 cfg
->beginiofunc
= strdup(s
);
761 case 22: /* abortio_func */
763 exitfileerror(20, "abortio_func not valid config option when in a class section\n");
764 if (cfg
->modtype
!= DEVICE
)
765 exitfileerror(20, "abortio_func specified when not a device\n");
766 cfg
->abortiofunc
= strdup(s
);
769 case 23: /* dispatcher */
771 exitfileerror(20, "dispatcher specified when not a BOOPSI class\n");
772 cl
->dispatcher
= strdup(s
);
773 /* function references are not needed when dispatcher is specified */
774 cfg
->intcfg
|= CFG_NOREADREF
;
777 case 24: /* initpri */
783 count
= sscanf(s
, "%d%c", &cl
->initpri
, &dummy
);
785 cl
->initpri
< -128 || cl
->initpri
> 127
788 exitfileerror(20, "initpri number format error\n");
792 exitfileerror(20, "initpri only valid config option for a BOOPSI class\n");
797 exitfileerror(20, "type only valid config option in a class section\n");
798 if (strcmp(s
,"mcc")==0)
800 else if (strcmp(s
,"mui")==0)
802 else if (strcmp(s
,"mcp")==0)
804 else if (strcmp(s
, "image")==0)
805 cl
->classtype
= IMAGE
;
806 else if (strcmp(s
, "gadget")==0)
807 cl
->classtype
= GADGET
;
808 else if (strcmp(s
, "datatype")==0)
809 cl
->classtype
= DATATYPE
;
810 else if (strcmp(s
, "class")==0)
811 cl
->classtype
= CLASS
;
812 else if (strcmp(s
, "hidd")==0)
813 cl
->classtype
= HIDD
;
816 fprintf(stderr
, "Unknown type \"%s\" specified\n", s
);
822 else /* Line starts with ## */
825 while (isspace(*s
)) s
++;
826 if (strncmp(s
, "end", 3)!=0)
827 exitfileerror(20, "\"##end config\" expected\n");
831 exitfileerror(20, "\"##end config\" expected\n");
833 while (isspace(*s
)) s
++;
834 if (strncmp(s
, "config", 6)!=0)
835 exitfileerror(20, "\"##end config\" expected\n");
838 while (isspace(*s
)) s
++;
840 exitfileerror(20, "\"##end config\" expected\n");
846 /* When not in a class section fill in default values for fields in cfg */
849 if (cfg
->basename
==NULL
)
851 cfg
->basename
= strdup(cfg
->modulename
);
852 *cfg
->basename
= toupper(*cfg
->basename
);
854 if (cfg
->libbase
==NULL
)
856 unsigned int len
= strlen(cfg
->basename
)+5;
857 cfg
->libbase
= malloc(len
);
858 snprintf(cfg
->libbase
, len
, "%sBase", cfg
->basename
);
860 if (cfg
->libbasetype
== NULL
&& libbasetypeextern
!= NULL
)
861 cfg
->libbasetype
= strdup(libbasetypeextern
);
862 if (cfg
->sysbase_field
!= NULL
&& cfg
->libbasetype
== NULL
)
863 exitfileerror(20, "sysbase_field specified when no libbasetype is given\n");
864 if (cfg
->seglist_field
!= NULL
&& cfg
->libbasetype
== NULL
)
865 exitfileerror(20, "seglist_field specified when no libbasetype is given\n");
867 /* Set default date to current date */
868 if (cfg
->datestring
== NULL
)
871 time_t now
= time(NULL
);
873 strftime(tmpbuf
, sizeof(tmpbuf
), "%d.%m.%Y", localtime(&now
));
875 cfg
->datestring
= strdup(tmpbuf
);
878 if (cfg
->copyright
== NULL
)
881 if ( (cfg
->beginiofunc
!= NULL
&& cfg
->abortiofunc
== NULL
)
882 || (cfg
->beginiofunc
== NULL
&& cfg
->abortiofunc
!= NULL
)
884 exitfileerror(20, "please specify both beginio_func and abortio_func\n");
886 if (libbasetypeextern
==NULL
)
888 switch (cfg
->modtype
)
891 cfg
->libbasetypeptrextern
= "struct Device *";
894 cfg
->libbasetypeptrextern
= "APTR ";
903 cfg
->libbasetypeptrextern
= "struct Library *";
906 fprintf(stderr
, "Internal error: Unsupported modtype for libbasetypeptrextern\n");
912 cfg
->libbasetypeptrextern
= malloc(strlen(libbasetypeextern
)+3);
913 strcpy(cfg
->libbasetypeptrextern
, libbasetypeextern
);
914 strcat(cfg
->libbasetypeptrextern
, " *");
915 free(libbasetypeextern
);
919 /* When class was given too fill in some defaults when not specified */
922 if (cl
->classtype
== UNSPECIFIED
)
923 cl
->classtype
= CLASS
;
925 if (cl
->basename
== NULL
)
928 cl
->basename
= cfg
->basename
;
930 exitfileerror(20, "basename has to be specified in the config section inside of a class section\n");
933 /* MUI classes are always private */
934 if (cl
->classtype
== MUI
|| cl
->classtype
== MCC
|| cl
->classtype
== MCP
)
935 cl
->options
|= COPTION_PRIVATE
;
937 if (cl
->classid
== NULL
938 && (cl
->classtype
!= MUI
&& cl
->classtype
!= MCC
&& cl
->classtype
!= MCP
)
941 if (cl
->classtype
== HIDD
)
943 cl
->options
&= !COPTION_PRIVATE
;
945 else if (cl
->options
& COPTION_PRIVATE
)
947 cl
->classid
= "NULL";
953 if (cl
->classtype
== GADGET
|| cl
->classtype
== IMAGE
|| cl
->classtype
== CLASS
)
955 sprintf(s
, "\"%sclass\"", inclass
? cl
->basename
: cfg
->modulename
);
957 else if (cl
->classtype
== DATATYPE
)
959 sprintf(s
, "\"%s.datatype\"", inclass
? cl
->basename
: cfg
->modulename
);
961 cl
->classid
= strdup(s
);
965 /* Only specify superclass or superclass_field */
966 if (cl
->superclass
!= NULL
&& cl
->superclass_field
!= NULL
)
967 exitfileerror(20, "Only specify one of superclass or superclass_field in config section\n");
969 /* Give default value to superclass if it is not specified */
970 if (cl
->superclass
== NULL
&& cl
->superclass
== NULL
)
972 switch (cl
->classtype
)
976 cl
->superclass
= "MUIC_Area";
979 cl
->superclass
= "MUIC_Mccprefs";
982 cl
->superclass
= "IMAGECLASS";
985 cl
->superclass
= "GADGETCLASS";
988 cl
->superclass
= "DATATYPESCLASS";
991 cl
->superclass
= "ROOTCLASS";
994 cl
->superclass
= "CLID_Root";
997 exitfileerror(20, "Internal error: unhandled classtype in readsectionconfig\n");
1004 static void readsectioncdef(struct config
*cfg
)
1013 exitfileerror(20, "unexptected end of file in section cdef\n");
1015 if (strncmp(line
, "##", 2)!=0)
1017 slist_append(&cfg
->cdeflines
, line
);
1022 while (isspace(*s
)) s
++;
1023 if (strncmp(s
, "end", 3)!=0)
1024 exitfileerror(20, "\"##end cdef\" expected\n");
1027 while (isspace(*s
)) s
++;
1028 if (strncmp(s
, "cdef", 4)!=0)
1029 exitfileerror(20, "\"##end cdef\" expected\n");
1032 while (isspace(*s
)) s
++;
1034 exitfileerror(20, "unexpected character at position %d\n");
1041 static void readsectioncdefprivate(struct config
*cfg
)
1050 exitfileerror(20, "unexptected end of file in section cdef\n");
1052 if (strncmp(line
, "##", 2)!=0)
1054 slist_append(&cfg
->cdefprivatelines
, line
);
1059 while (isspace(*s
)) s
++;
1060 if (strncmp(s
, "end", 3)!=0)
1061 exitfileerror(20, "\"##end cdefprivate\" expected\n");
1064 while (isspace(*s
)) s
++;
1065 if (strncmp(s
, "cdefprivate", 11)!=0)
1066 exitfileerror(20, "\"##end cdefprivate\" expected\n");
1069 while (isspace(*s
)) s
++;
1071 exitfileerror(20, "unexpected character at position %d\n");
1078 static void readsectionfunctionlist(struct config
*cfg
)
1081 char *line
, *s
, *s2
;
1082 unsigned int lvo
= cfg
->firstlvo
;
1083 struct functionhead
**funclistptr
= &cfg
->funclist
;
1085 if (cfg
->basename
==NULL
)
1086 exitfileerror(20, "section functionlist has to come after section config\n");
1092 exitfileerror(20, "unexptected EOF in functionlist section\n");
1093 if (strlen(line
)==0)
1095 if (*funclistptr
!= NULL
)
1096 funclistptr
= &((*funclistptr
)->next
);
1099 else if (isspace(*line
))
1102 while (isspace(*s
)) s
++;
1105 if (*funclistptr
!= NULL
)
1106 funclistptr
= &((*funclistptr
)->next
);
1110 exitfileerror(20, "no space allowed before functionname\n");
1112 else if (strncmp(line
, "##", 2)==0)
1115 while (isspace(*s
)) s
++;
1116 if (strncmp(s
, "end", 3)!=0)
1117 exitfileerror(20, "\"##end functionlist\" expected\n");
1120 while (isspace(*s
)) s
++;
1121 if (strncmp(s
, "functionlist", 12)!=0)
1122 exitfileerror(20, "\"##end functionlist\" expected\n");
1125 while (isspace(*s
)) s
++;
1127 exitfileerror(20, "unexpected character on position %d\n", s
-line
);
1131 else if (*line
=='.')
1134 if (strncmp(s
, "skip", 4)==0)
1140 exitfileerror(20, "syntax is '.skip n'\n");
1142 n
=strtol(s
, &s2
, 10);
1144 exitfileerror(20, "positive number expected\n");
1146 while (isspace(*s2
)) s2
++;
1148 exitfileerror(20, "syntax is '.skip n'\n");
1149 if (*funclistptr
!= NULL
)
1150 funclistptr
= &((*funclistptr
)->next
);
1153 else if (strncmp(s
, "alias", 5)==0)
1158 exitfileerror(20, "syntax is '.alias name'\n");
1160 while (isspace(*s
)) s
++;
1161 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1162 exitfileerror(20, "syntax is '.alias name'\n");
1166 while (isalnum(*s
) || *s
== '_') s
++;
1173 } while (isspace(*s
));
1177 exitfileerror(20, "syntax is '.alias name'\n");
1179 if (*funclistptr
== NULL
)
1180 exitfileerror(20, ".alias has to come after a function declaration\n");
1182 slist_append(&(*funclistptr
)->aliases
, s2
);
1183 cfg
->intcfg
|= CFG_GENASTUBS
;
1185 else if (strncmp(s
, "cfunction", 9)==0)
1187 if (*funclistptr
== NULL
)
1188 exitfileerror(20, ".cfunction has to come after a function declaration\n");
1190 (*funclistptr
)->libcall
= REGISTER
;
1192 else if (strncmp(s
, "private", 7)==0)
1194 if (*funclistptr
== NULL
)
1195 exitfileerror(20, ".private has to come after a function declaration\n");
1197 (*funclistptr
)->priv
= 1;
1199 else if (strncmp(s
, "novararg", 8)==0)
1201 if (*funclistptr
== NULL
)
1202 exitfileerror(20, ".novararg has to come after a function declaration\n");
1204 (*funclistptr
)->novararg
= 1;
1207 exitfileerror(20, "Syntax error");
1209 else if (*line
!='#') /* Ignore line that is a comment, e.g. that starts with a # */
1211 /* The line is a function prototype. It can have two syntax
1212 * type funcname(argproto1, argproto2, ...)
1213 * type funcname(argproto1, argproto2, ...) (reg1, reg2, ...)
1214 * The former is for C type function argument passing, the latter for
1215 * register argument passing.
1217 char c
, *args
[64], *regs
[64], *funcname
;
1218 int len
, argcount
= 0, regcount
= 0, brcount
= 0;
1220 /* Parse 'type functionname' at the beginning of the line */
1221 s
= strchr(line
, '(');
1223 exitfileerror(20, "( expected at position %d\n", strlen(line
) + 1);
1226 while (isspace(*(s2
-1)))
1230 while (s2
> line
&& !isspace(*(s2
-1)) && !(*(s2
-1) == '*'))
1234 exitfileerror(20, "No type specifier before function name\n");
1236 if (*funclistptr
!= NULL
)
1237 funclistptr
= &((*funclistptr
)->next
);
1238 *funclistptr
= newfunctionhead(s2
, STACK
);
1240 while (isspace(*(s2
-1)))
1243 (*funclistptr
)->type
= strdup(line
);
1244 (*funclistptr
)->lvo
= lvo
;
1247 /* Parse function prototype */
1264 && !(brcount
== 0 && (*s
== ',' || *s
== ')'))
1274 exitfileerror(20, "Unexected ')' at position %d\n", s
-line
+1);
1281 exitfileerror(20, "'(' without ')'");
1284 while (isspace(*(s2
-1)))
1288 if (!(s2
> args
[argcount
- 1]))
1289 exitfileerror(20, "Syntax error in function prototype\n");
1295 while (*s
!= '\0' && isspace(*s
))
1300 /* Parse registers specifications if available otherwise this prototype for C type argument passing */
1302 /* There may be no register specified with () so be sure then c is == ')' */
1317 if (memchr("AD",s
[0],2)!=NULL
&& memchr("01234567",s
[1],8)!=NULL
)
1325 if (strchr(regs
[0], '/') == NULL
)
1326 exitfileerror(20, "Either all arguments has to in two registers or none\n");
1330 if (s
[0] == s
[-3] && s
[1] == s
[-2] + 1)
1337 "wrong register specification \"%s\" for argument %u\n",
1338 regs
[regcount
-1], regcount
1342 exitfileerror(20, "maximum two arguments passed in two registers allowed\n");
1348 "wrong register \"%s\" for argument %u\n",
1349 regs
[regcount
-1], regcount
1358 exitfileerror(20, "'(' without ')'\n");
1359 if (c
!= ',' && c
!= ')')
1360 exitfileerror(20, "',' or ')' expected at position %d\n", s
-line
+1);
1366 while (isspace(*s
)) s
++;
1368 exitfileerror(20, "wrong char '%c' at position %d\n", *s
, (int)(s
-line
) + 1);
1370 if (argcount
!= regcount
)
1371 exitfileerror(20, "Number of arguments (%d) and registers (%d) mismatch\n",
1375 (*funclistptr
)->libcall
= REGISTERMACRO
;
1376 for (i
= 0; i
< argcount
; i
++)
1377 funcaddarg(*funclistptr
, args
[i
], regs
[i
]);
1379 else if (*s
== '\0')
1380 { /* No registers specified */
1381 for (i
= 0; i
< argcount
; i
++)
1382 funcaddarg(*funclistptr
, args
[i
], NULL
);
1383 cfg
->intcfg
|= CFG_GENASTUBS
;
1386 exitfileerror(20, "wrong char '%c' at position %d\n", *s
, (int)(s
-line
) + 1);
1391 static void readsectionmethodlist(struct classinfo
*cl
)
1394 char *line
, *s
, *s2
;
1395 struct functionhead
**methlistptr
= &cl
->methlist
;
1396 struct stringlist
*interface
= NULL
;
1398 if (cl
->basename
==NULL
)
1399 exitfileerror(20, "section methodlist has to come after section config\n");
1405 exitfileerror(20, "unexptected EOF in methodlist section\n");
1407 /* Ignore empty lines or lines that qre a comment, e.g. that starts with a # */
1408 if (strlen(line
)==0 || (line
[0] == '#' && line
[1] != '#'))
1412 exitfileerror(20, "No space allowed at start of the line\n");
1414 if (strncmp(line
, "##", 2)==0) /* Is this the end ? */
1417 while (isspace(*s
)) s
++;
1418 if (strncmp(s
, "end", 3)!=0)
1419 exitfileerror(20, "\"##end methodlist\" expected\n");
1422 while (isspace(*s
)) s
++;
1423 if (strncmp(s
, "methodlist", 10)!=0)
1424 exitfileerror(20, "\"##end methodlist\" expected\n");
1427 while (isspace(*s
)) s
++;
1429 exitfileerror(20, "unexpected character on position %d\n", s
-line
);
1439 if (strncmp(s
, "alias", 5)==0)
1444 exitfileerror(20, "syntax is '.alias name'\n");
1446 while (isspace(*s
)) s
++;
1447 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1448 exitfileerror(20, "syntax is '.alias name'\n");
1452 while (isalnum(*s
) || *s
== '_') s
++;
1459 } while (isspace(*s
));
1463 exitfileerror(20, "syntax is '.alias name'\n");
1465 if (*methlistptr
== NULL
)
1466 exitfileerror(20, ".alias has to come after a function declaration\n");
1468 slist_append(&(*methlistptr
)->aliases
, s2
);
1470 else if (strncmp(s
, "function", 8) == 0)
1475 exitfileerror(20, "Syntax error\n");
1477 while (isspace(*s
)) s
++;
1478 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1479 exitfileerror(20, "syntax is '.function name'\n");
1483 while (isalnum(*s
) || *s
== '_') s
++;
1490 } while (isspace(*s
));
1494 exitfileerror(20, "syntax is '.function name'\n");
1496 if (*methlistptr
== NULL
)
1497 exitfileerror(20, ".function has to come after a function declaration\n");
1499 free((*methlistptr
)->name
);
1500 (*methlistptr
)->name
= strdup(s2
);
1502 else if (strncmp(s
, "interface", 9) == 0)
1504 if (cl
->classtype
!= HIDD
)
1505 exitfileerror(20, "interface only valid for a HIDD\n");
1510 exitfileerror(20, "Syntax error\n");
1512 while (isspace(*s
)) s
++;
1513 if (*s
== '\0' || !isalpha(*s
))
1514 exitfileerror(20, "syntax is '.interface name'\n");
1518 while (isalnum(*s
) || *s
== '_') s
++;
1525 } while (isspace(*s
));
1529 exitfileerror(20, "syntax is '.interface name'\n");
1531 interface
= slist_append(&cl
->interfaces
, s2
);
1534 exitfileerror(20, "Syntax error");
1536 else if (isalpha(*line
))
1540 for (s
= line
+ 1; isalnum(*s
) || *s
== '_'; s
++)
1543 if (cl
->classtype
== HIDD
&& interface
== NULL
)
1544 exitfileerror(20, "For a HIDD the first method has to come after an .interface line\n");
1547 exitfileerror(20, "Only letters, digits and an underscore allowed in a methodname\n");
1549 if (*methlistptr
!= NULL
)
1550 methlistptr
= &((*methlistptr
)->next
);
1551 if (cl
->classtype
!= HIDD
)
1553 if (snprintf(stmp
, 256, "%s__%s", cl
->basename
, line
) >= 256)
1554 exitfileerror(20, "Method name too large\n");
1556 *methlistptr
= newfunctionhead(stmp
, STACK
);
1557 (*methlistptr
)->type
= "IPTR";
1558 funcaddarg(*methlistptr
, "Class *cl", NULL
);
1559 funcaddarg(*methlistptr
, "Object *o", NULL
);
1560 funcaddarg(*methlistptr
, "Msg msg", NULL
);
1564 if (snprintf(stmp
, 256, "%s__%s__%s", cl
->basename
, interface
->s
, line
) >= 256)
1565 exitfileerror(20, "Method name too large\n");
1567 *methlistptr
= newfunctionhead(stmp
, STACK
);
1568 (*methlistptr
)->type
= "IPTR";
1569 funcaddarg(*methlistptr
, "OOP_Class *cl", NULL
);
1570 funcaddarg(*methlistptr
, "OOP_Object *o", NULL
);
1571 funcaddarg(*methlistptr
, "OOP_Msg msg", NULL
);
1572 (*methlistptr
)->interface
= interface
;
1573 if (snprintf(stmp
, 256, "mo%s_%s", interface
->s
, line
) >= 256)
1574 exitfileerror(20, "Method name too large\n");
1575 (*methlistptr
)->method
= strdup(stmp
);
1577 slist_append(&(*methlistptr
)->aliases
, line
);
1580 exitfileerror(20, "Methodname has to begin with a letter\n");
1585 readsectionclass(struct config
*cfg
)
1588 struct classinfo
*cl
;
1591 s
= readsections(cfg
, cl
, 1);
1593 exitfileerror(20, "Unexpected end of file\n");
1595 if (strncmp(s
, "##", 2) != 0)
1596 exitfileerror(20, "'##end class' expected\n");
1599 while (isspace(*s
)) s
++;
1601 if (strncmp(s
, "end", 3) != 0)
1602 exitfileerror(20, "'##end class' expected\n");
1606 exitfileerror(20, "'##end class' expected\n");
1607 while (isspace(*s
)) s
++;
1609 if (strncmp(s
, "class", 5) != 0)
1610 exitfileerror(20, "'##end class' expected\n");
1613 while (isspace(*s
)) s
++;
1615 exitfileerror(20, "'##end class' expected\n");
1618 static struct classinfo
*newclass(struct config
*cfg
)
1620 struct classinfo
*cl
, *classlistit
;
1622 cl
= malloc(sizeof(struct classinfo
));
1625 fprintf(stderr
, "Out of memory\n");
1628 memset(cl
, 0, sizeof(struct classinfo
));
1630 /* By default the classes are initialized with a priority of 1 so they
1631 * are initialized before any user added initialization with priority 1
1635 if (cfg
->classlist
== NULL
)
1636 cfg
->classlist
= cl
;
1641 classlistit
= cfg
->classlist
;
1642 classlistit
->next
!= NULL
;
1643 classlistit
= classlistit
->next
1646 classlistit
->next
= cl
;