2 Copyright © 1995-2012, The AROS Development Team. All rights reserved.
5 Code to parse the command line options and the module config file for
17 #include "functionhead.h"
20 const static char bannertemplate
[] =
22 " *** Automatically generated from '%s'. Edits will be lost. ***\n"
23 " Copyright © 1995-2012, The AROS Development Team. All rights reserved.\n"
27 getBanner(struct config
* config
)
29 int bannerlength
= strlen(config
->conffile
) + strlen(bannertemplate
) -1;
30 char * banner
= malloc(bannerlength
);
32 snprintf (banner
, bannerlength
, bannertemplate
, config
->conffile
);
38 freeBanner(char *banner
)
43 const static char usage
[] =
45 "Usage: genmodule [-c conffile] [-s suffix] [-d gendir] [-n]\n"
46 " {writefiles|writemakefile|writeincludes|writelibdefs|writefunclist|writefd|writeskel} modname modtype\n"
49 static void readconfig(struct config
*);
50 static struct classinfo
*newclass(struct config
*);
51 static struct handlerinfo
*newhandler(struct config
*);
53 /* the method prefices for the supported classes */
54 static const char *muimprefix
[] =
60 static const char *gadgetmprefix
[] =
67 static const char *dtmprefix
[] =
76 /* Create a config struct. Initialize with the values from the programs command
77 * line arguments and the contents of the modules .conf file
79 struct config
*initconfig(int argc
, char **argv
)
82 char *s
, **argvit
= argv
+ 1;
85 cfg
= malloc(sizeof(struct config
));
88 fprintf(stderr
, "Out of memory\n");
92 memset(cfg
, 0, sizeof(struct config
));
94 while ((c
= getopt(argc
, argv
, ":c:s:d:v:")) != -1)
98 fprintf(stderr
, "Option -%c needs an argument\n",optopt
);
105 cfg
->conffile
= optarg
;
109 cfg
->suffix
= optarg
;
114 /* Remove / at end if present */
115 if ((optarg
)[strlen(*argvit
)-1]=='/') (optarg
)[strlen(optarg
)-1]='\0';
116 cfg
->gendir
= optarg
;
120 cfg
->versionextra
= optarg
;
124 fprintf(stderr
, "Internal error: Unhandled option\n");
129 if (optind
+ 3 != argc
)
131 fprintf(stderr
, "Wrong number of arguments.\n%s", usage
);
135 if (strcmp(argv
[optind
], "writefiles") == 0)
137 cfg
->command
= FILES
;
139 else if (strcmp(argv
[optind
], "writemakefile") == 0)
141 cfg
->command
= MAKEFILE
;
143 else if (strcmp(argv
[optind
], "writeincludes") == 0)
145 cfg
->command
= INCLUDES
;
147 else if (strcmp(argv
[optind
], "writelibdefs") == 0)
149 cfg
->command
= LIBDEFS
;
151 else if (strcmp(argv
[optind
], "writefunclist") == 0)
153 cfg
->command
= WRITEFUNCLIST
;
155 else if (strcmp(argv
[optind
], "writefd") == 0)
157 cfg
->command
= WRITEFD
;
159 else if (strcmp(argv
[optind
], "writeskel") == 0)
161 cfg
->command
= WRITESKEL
;
165 fprintf(stderr
, "Unrecognized argument \"%s\"\n%s", argv
[optind
], usage
);
169 cfg
->modulename
= argv
[optind
+1];
170 cfg
->modulenameupper
= strdup(cfg
->modulename
);
171 for (s
=cfg
->modulenameupper
; *s
!='\0'; *s
= toupper(*s
), s
++) {
172 if (!isalnum(*s
)) *s
= '_';
175 if (strcmp(argv
[optind
+2],"library")==0)
177 cfg
->modtype
= LIBRARY
;
178 cfg
->moddir
= "Libs";
180 else if (strcmp(argv
[optind
+2],"mcc")==0)
183 cfg
->moddir
= "Classes/Zune";
185 else if (strcmp(argv
[optind
+2],"mui")==0)
188 cfg
->moddir
= "Classes/Zune";
190 else if (strcmp(argv
[optind
+2],"mcp")==0)
193 cfg
->moddir
= "Classes/Zune";
195 else if (strcmp(argv
[optind
+2], "device")==0)
197 cfg
->modtype
= DEVICE
;
198 cfg
->moddir
= "Devs";
200 else if (strcmp(argv
[optind
+2], "resource")==0)
202 cfg
->modtype
= RESOURCE
;
203 cfg
->moddir
= "Devs";
205 else if (strcmp(argv
[optind
+2], "gadget")==0)
207 cfg
->modtype
= GADGET
;
208 cfg
->moddir
= "Classes/Gadgets";
210 else if (strcmp(argv
[optind
+2], "datatype")==0)
212 cfg
->modtype
= DATATYPE
;
213 cfg
->moddir
= "Classes/DataTypes";
215 else if (strcmp(argv
[optind
+2], "usbclass")==0)
217 cfg
->modtype
= USBCLASS
;
218 cfg
->moddir
= "Classes/USB";
221 cfg
->suffix
= "class";
225 else if (strcmp(argv
[optind
+2], "hidd")==0)
228 cfg
->moddir
= "Devs/Drivers";
230 else if (strcmp(argv
[optind
+2], "handler")==0)
232 cfg
->modtype
= HANDLER
;
233 cfg
->moddir
= "$(AROS_DIR_FS)";
237 fprintf(stderr
, "Unknown modtype \"%s\" specified for second argument\n", argv
[2]);
242 cfg
->suffix
= argv
[optind
+2];
244 /* Fill fields with default value if not specified on the command line */
248 if (cfg
->conffile
== NULL
)
250 snprintf(tmpbuf
, sizeof(tmpbuf
), "%s.conf", cfg
->modulename
);
251 cfg
->conffile
= strdup(tmpbuf
);
254 if (cfg
->gendir
== NULL
)
260 /* For a device add the functions given in beginiofunc and abortiofunc to the functionlist
261 * if they are provided
263 if (cfg
->beginiofunc
!= NULL
)
265 struct functionhead
*funchead
;
267 cfg
->intcfg
|= CFG_NOREADFUNCS
;
269 /* Add beginio_func to the list of functions */
270 funchead
= newfunctionhead(cfg
->beginiofunc
, REGISTERMACRO
);
271 funchead
->type
= strdup("void");
273 funcaddarg(funchead
, "struct IORequest *ioreq", "A1");
275 funchead
->next
= cfg
->funclist
;
276 cfg
->funclist
= funchead
;
278 /* Add abortio_func to the list of functions */
279 funchead
= newfunctionhead(cfg
->abortiofunc
, REGISTERMACRO
);
280 funchead
->type
= strdup("LONG");
282 funcaddarg(funchead
, "struct IORequest *ioreq", "A1");
284 funchead
->next
= cfg
->funclist
->next
;
285 cfg
->funclist
->next
= funchead
;
287 else if (cfg
->modtype
== DEVICE
&& cfg
->intcfg
& CFG_NOREADFUNCS
)
292 "beginio_func and abortio_func missing for a device with a non empty function list\n"
300 /* Functions to read configuration from the configuration file */
302 #include "fileread.h"
304 static char *readsections(struct config
*, struct classinfo
*, int);
305 static void readsectionconfig(struct config
*, struct classinfo
*, int);
306 static void readsectioncdef(struct config
*);
307 static void readsectioncdefprivate(struct config
*);
308 static void readsectionstartup(struct config
*);
309 static void readsectionfunctionlist(struct config
*);
310 static void readsectionmethodlist(struct classinfo
*);
311 static void readsectionclass(struct config
*);
312 static void readsectionhandler(struct config
*);
314 static void readconfig(struct config
*cfg
)
316 struct classinfo
*mainclass
= NULL
;
318 /* Create a classinfo structure if this module is a class */
319 switch (cfg
->modtype
)
334 mainclass
= newclass(cfg
);
335 mainclass
->classtype
= cfg
->modtype
;
339 fprintf(stderr
, "Internal error: unsupported modtype for classinfo creation\n");
343 switch (cfg
->modtype
)
356 mainclass
->boopsimprefix
= muimprefix
;
364 mainclass
->boopsimprefix
= gadgetmprefix
;
368 mainclass
->boopsimprefix
= dtmprefix
;
372 /* FIXME: need boopsimprefix ? */
375 fprintf(stderr
, "Internal error: unsupported modtype for firstlvo\n");
379 if (!fileopen(cfg
->conffile
))
381 fprintf(stderr
, "In readconfig: Could not open %s\n", cfg
->conffile
);
385 /* Read all sections and see that we are at the end of the file */
386 if (readsections(cfg
, mainclass
, 0) != NULL
)
387 exitfileerror(20, "Syntax error");
392 /* readsections will scan through all the sections in the config file.
394 * struct config *cfg: The module config data which may be updated by
395 * the information in the sections
396 * struct classinfo *cl: The classdata to be filled with data from the sections.
397 * This may be NULL if this is the main part of the configuration file and the
398 * type of the module is not a class
399 * int inclass: Boolean to indicate if we are in a class part. If not we are in the main
400 * part of the config file.
402 static char *readsections(struct config
*cfg
, struct classinfo
*cl
, int inclass
)
407 while ((line
=readline())!=NULL
)
409 if (strncmp(line
, "##", 2)==0)
411 static char *parts
[] =
413 "config", "cdefprivate", "cdef", "startup", "functionlist", "methodlist", "class", "handler",
415 const unsigned int nums
= sizeof(parts
)/sizeof(char *);
416 unsigned int partnum
;
420 while (isspace(*s
)) s
++;
422 if (strncmp(s
, "begin", 5)!=0)
427 exitfileerror(20, "space after begin expected\n");
428 while (isspace(*s
)) s
++;
430 for (i
= 0, partnum
= 0; partnum
==0 && i
<nums
; i
++)
432 if (strncmp(s
, parts
[i
], strlen(parts
[i
]))==0)
435 s
+= strlen(parts
[i
]);
436 while (isspace(*s
)) s
++;
438 exitfileerror(20, "unexpected character on position %d\n", s
-line
);
442 exitfileerror(20, "unknown start of section\n");
446 readsectionconfig(cfg
, cl
, inclass
);
450 case 2: /* cdefprivate */
452 exitfileerror(20, "cdefprivate section not allowed in class section\n");
453 readsectioncdefprivate(cfg
);
458 exitfileerror(20, "cdef section not allowed in class section\n");
459 readsectioncdef(cfg
);
462 case 4: /* startup */
464 exitfileerror(20, "startup section not allowed in class section\n");
465 readsectionstartup(cfg
);
468 case 5: /* functionlist */
470 exitfileerror(20, "functionlist section not allow in class section\n");
471 readsectionfunctionlist(cfg
);
472 cfg
->intcfg
|= CFG_NOREADFUNCS
;
475 case 6: /* methodlist */
477 exitfileerror(20, "methodlist section when not in a class\n");
478 readsectionmethodlist(cl
);
479 cfg
->intcfg
|= CFG_NOREADFUNCS
;
484 exitfileerror(20, "class section may not be nested\n");
485 readsectionclass(cfg
);
487 case 8: /* handler */
488 readsectionhandler(cfg
);
492 else if (strlen(line
)!=0)
493 filewarning("warning line outside section ignored\n");
499 exitfileerror(20, "No config section in conffile\n");
501 /* If no indication was given for generating includes or not
502 decide on module type and if there are functions
504 if(!((cfg
->options
& OPTION_INCLUDES
) || (cfg
->options
& OPTION_NOINCLUDES
)))
506 switch (cfg
->modtype
)
510 cfg
->options
|= OPTION_INCLUDES
;
518 cfg
->options
|= OPTION_NOINCLUDES
;
523 (cfg
->funclist
!= NULL
)
524 || (cfg
->cdeflines
!= NULL
)
525 || strcmp(cfg
->libbasetypeptrextern
, "struct Device *") != 0
526 ) ? OPTION_INCLUDES
: OPTION_NOINCLUDES
;
533 (cfg
->funclist
!= NULL
)
534 ) ? OPTION_INCLUDES
: OPTION_NOINCLUDES
;
538 fprintf(stderr
, "Internal error writemakefile: unhandled modtype for includes\n");
544 /* If no indication was given for not generating stubs only generate them if
545 * the module has functions
547 if(!((cfg
->options
& OPTION_STUBS
) || (cfg
->options
& OPTION_NOSTUBS
)))
549 switch (cfg
->modtype
)
552 cfg
->options
|= (cfg
->funclist
!= NULL
) ? OPTION_STUBS
: OPTION_NOSTUBS
;
565 cfg
->options
|= OPTION_NOSTUBS
;
569 fprintf(stderr
, "Internal error writemakefile: unhandled modtype for stubs\n");
575 /* If no indication was given for generating autoinit code or not
576 decide on module type
578 if(!((cfg
->options
& OPTION_AUTOINIT
) || (cfg
->options
& OPTION_NOAUTOINIT
)))
580 switch (cfg
->modtype
)
583 cfg
->options
|= OPTION_AUTOINIT
;
596 cfg
->options
|= OPTION_NOAUTOINIT
;
600 fprintf(stderr
, "Internal error writemakefile: unhandled modtype for autoinit\n");
606 if ((cfg
->modtype
== RESOURCE
) || (cfg
->modtype
== HANDLER
))
607 /* Enforce noopenclose for resources and handlers */
608 cfg
->options
|= OPTION_NOOPENCLOSE
;
609 else if (!(cfg
->options
& OPTION_SELFINIT
))
610 /* Enforce using RTF_AUTOINIT for everything except resources */
611 cfg
->options
|= OPTION_RESAUTOINIT
;
617 static void readsectionconfig(struct config
*cfg
, struct classinfo
*cl
, int inclass
)
620 char *line
, *s
, *s2
, *libbasetypeextern
= NULL
;
627 exitfileerror(20, "unexpected end of file in section config\n");
629 if (strncmp(line
, "##", 2)!=0)
631 const char *names
[] =
633 "basename", "libbase", "libbasetype", "libbasetypeextern",
634 "version", "date", "copyright", "libcall", "forcebase", "superclass",
635 "superclass_field", "residentpri", "options", "sysbase_field",
636 "seglist_field", "rootbase_field", "classptr_field", "classptr_var",
637 "classid", "classdatatype", "beginio_func", "abortio_func", "dispatcher",
638 "initpri", "type", "addromtag", "oopbase_field"
640 const unsigned int namenums
= sizeof(names
)/sizeof(char *);
641 unsigned int namenum
;
643 for (i
= 0, namenum
= 0; namenum
==0 && i
<namenums
; i
++)
647 strncmp(line
, names
[i
], strlen(names
[i
]))==0
648 && isspace(*(line
+strlen(names
[i
])))
653 exitfileerror(20, "unrecognized configuration option\n");
655 s
= line
+ strlen(names
[namenum
-1]);
657 exitfileerror(20, "space character expected after \"%s\"\n", names
[namenum
-1]);
659 while (isspace(*s
)) s
++;
661 exitfileerror(20, "unexpected end of line\n");
664 while (isspace(*(s2
-1))) s2
--;
669 case 1: /* basename */
671 cfg
->basename
= strdup(s
);
673 cl
->basename
= strdup(s
);
676 case 2: /* libbase */
678 exitfileerror(20, "libbase not valid config option when in a class section\n");
679 cfg
->libbase
= strdup(s
);
682 case 3: /* libbasetype */
684 exitfileerror(20, "libbasetype not valid config option when in a class section\n");
685 cfg
->libbasetype
= strdup(s
);
688 case 4: /* libbasetypeextern */
690 exitfileerror(20, "libbasetype not valid config option when in a class section\n");
691 libbasetypeextern
= strdup(s
);
694 case 5: /* version */
696 exitfileerror(20, "version not valid config option when in a class section\n");
697 if (sscanf(s
, "%u.%u", &cfg
->majorversion
, &cfg
->minorversion
)!=2)
698 exitfileerror(20, "wrong version string \"%s\"\n", s
);
703 exitfileerror(20, "date not valid config option when in a class section\n");
705 if (strptime(s
, "%e.%m.%Y", &date
) == NULL
)
707 exitfileerror(20, "date string has to have d.m.yyyy format\n");
710 cfg
->datestring
= strdup(s
);
713 case 7: /* copyright */
715 exitfileerror(20, "copyright not valid config option when in a class section\n");
716 cfg
->copyright
= strdup(s
);
719 case 8: /* libcall */
720 fprintf(stderr
, "libcall specification is deprecated and ignored\n");
723 case 9: /* forcebase */
725 exitfileerror(20, "forcebase not valid config option when in a class section\n");
726 slist_append(&cfg
->forcelist
, s
);
729 case 10: /* superclass */
731 exitfileerror(20, "superclass specified when not a BOOPSI class\n");
732 cl
->superclass
= strdup(s
);
735 case 11: /* superclass_field */
737 exitfileerror(20, "superclass_field specified when not a BOOPSI class\n");
738 cl
->superclass_field
= strdup(s
);
741 case 12: /* residentpri */
747 count
= sscanf(s
, "%d%c", &cfg
->residentpri
, &dummy
);
749 cfg
->residentpri
< -128 || cfg
->residentpri
> 127
752 exitfileerror(20, "residentpri number format error\n");
756 exitfileerror(20, "residentpri not valid config option when in a class section\n");
759 case 13: /* options */
762 static const char *optionnames
[] =
764 "noautolib", "noexpunge", "noresident", "peropenerbase",
765 "pertaskbase", "includes", "noincludes", "nostubs",
766 "autoinit", "noautoinit", "resautoinit", "noopenclose",
769 const unsigned int optionnums
= sizeof(optionnames
)/sizeof(char *);
774 for (i
= 0, optionnum
= 0; optionnum
==0 && i
<optionnums
; i
++)
776 if (strncmp(s
, optionnames
[i
], strlen(optionnames
[i
]))==0)
779 s
+= strlen(optionnames
[i
]);
780 while (isspace(*s
)) s
++;
784 exitfileerror(20, "Unrecognized option\n");
788 exitfileerror(20, "Unrecognized option\n");
791 case 1: /* noautolib */
792 cfg
->options
|= OPTION_NOAUTOLIB
;
794 case 2: /* noexpunge */
795 cfg
->options
|= OPTION_NOEXPUNGE
;
797 case 3: /* noresident */
798 cfg
->options
|= OPTION_NORESIDENT
;
801 case 5: /* pertaskbase */
802 cfg
->options
|= OPTION_PERTASKBASE
;
804 case 4: /* peropenerbase */
805 if (cfg
->options
& OPTION_DUPBASE
)
806 exitfileerror(20, "Only one option peropenerbase or pertaskbase allowed\n");
807 cfg
->options
|= OPTION_DUPBASE
;
809 case 6: /* includes */
810 if (cfg
->options
& OPTION_NOINCLUDES
)
811 exitfileerror(20, "option includes and noincludes are incompatible\n");
812 cfg
->options
|= OPTION_INCLUDES
;
814 case 7: /* noincludes */
815 if (cfg
->options
& OPTION_INCLUDES
)
816 exitfileerror(20, "option includes and noincludes are incompatible\n");
817 cfg
->options
|= OPTION_NOINCLUDES
;
819 case 8: /* nostubs */
820 cfg
->options
|= OPTION_NOSTUBS
;
822 case 9: /* autoinit */
823 if (cfg
->options
& OPTION_NOAUTOINIT
)
824 exitfileerror(20, "option autoinit and noautoinit are incompatible\n");
825 cfg
->options
|= OPTION_AUTOINIT
;
827 case 10: /* noautoinit */
828 if (cfg
->options
& OPTION_AUTOINIT
)
829 exitfileerror(20, "option autoinit and noautoinit are incompatible\n");
830 cfg
->options
|= OPTION_NOAUTOINIT
;
832 case 11: /* resautoinit */
833 if (cfg
->options
& OPTION_SELFINIT
)
834 exitfileerror(20, "option resautoinit and selfinit are incompatible\n");
835 cfg
->options
|= OPTION_RESAUTOINIT
;
838 cfg
->options
|= OPTION_NOOPENCLOSE
;
840 case 13: /* noresautoinit */
841 if (cfg
->options
& OPTION_RESAUTOINIT
)
842 exitfileerror(20, "option resautoinit and selfinit are incompatible\n");
843 cfg
->options
|= OPTION_SELFINIT
;
846 while (isspace(*s
)) s
++;
851 static const char *optionnames
[] =
855 const unsigned int optionnums
= sizeof(optionnames
)/sizeof(char *);
860 for (i
= 0, optionnum
= 0; optionnum
==0 && i
<optionnums
; i
++)
862 if (strncmp(s
, optionnames
[i
], strlen(optionnames
[i
]))==0)
865 s
+= strlen(optionnames
[i
]);
866 while (isspace(*s
)) s
++;
870 exitfileerror(20, "Unrecognized option\n");
874 exitfileerror(20, "Unrecognized option\n");
877 case 1: /* private */
878 cl
->options
|= COPTION_PRIVATE
;
881 while (isspace(*s
)) s
++;
886 case 14: /* sysbase_field */
888 exitfileerror(20, "sysbase_field not valid config option when in a class section\n");
889 cfg
->sysbase_field
= strdup(s
);
892 case 15: /* seglist_field */
894 exitfileerror(20, "seglist_field not valid config option when in a class section\n");
895 cfg
->seglist_field
= strdup(s
);
898 case 16: /* rootbase_field */
900 exitfileerror(20, "rootbase_field not valid config option when in a class section\n");
901 cfg
->rootbase_field
= strdup(s
);
904 case 17: /* classptr_field */
910 "classptr_field specified when not a BOOPSI class\n"
913 cl
->classptr_field
= strdup(s
);
916 case 18: /* classptr_var */
922 "classptr_var specified when not a BOOPSI class\n"
925 cl
->classptr_var
= strdup(s
);
928 case 19: /* classid */
930 exitfileerror(20, "classid specified when not a BOOPSI class\n");
931 if (cl
->classid
!= NULL
)
932 exitfileerror(20, "classid specified twice\n");
933 cl
->classid
= strdup(s
);
934 if (strcmp(cl
->classid
, "NULL") == 0)
935 cl
->options
|= COPTION_PRIVATE
;
938 case 20: /* classdatatype */
940 exitfileerror(20, "classdatatype specified when not a BOOPSI class\n");
941 cl
->classdatatype
= strdup(s
);
944 case 21: /* beginio_func */
946 exitfileerror(20, "beginio_func not valid config option when in a class section\n");
947 if (cfg
->modtype
!= DEVICE
)
948 exitfileerror(20, "beginio_func specified when not a device\n");
949 cfg
->beginiofunc
= strdup(s
);
952 case 22: /* abortio_func */
954 exitfileerror(20, "abortio_func not valid config option when in a class section\n");
955 if (cfg
->modtype
!= DEVICE
)
956 exitfileerror(20, "abortio_func specified when not a device\n");
957 cfg
->abortiofunc
= strdup(s
);
960 case 23: /* dispatcher */
962 exitfileerror(20, "dispatcher specified when not a BOOPSI class\n");
963 cl
->dispatcher
= strdup(s
);
964 /* function references are not needed when dispatcher is specified */
965 cfg
->intcfg
|= CFG_NOREADFUNCS
;
968 case 24: /* initpri */
974 count
= sscanf(s
, "%d%c", &cl
->initpri
, &dummy
);
976 cl
->initpri
< -128 || cl
->initpri
> 127
979 exitfileerror(20, "initpri number format error\n");
983 exitfileerror(20, "initpri only valid config option for a BOOPSI class\n");
988 exitfileerror(20, "type only valid config option in a class section\n");
989 if (strcmp(s
,"mcc")==0)
991 else if (strcmp(s
,"mui")==0)
993 else if (strcmp(s
,"mcp")==0)
995 else if (strcmp(s
, "image")==0)
996 cl
->classtype
= IMAGE
;
997 else if (strcmp(s
, "gadget")==0)
998 cl
->classtype
= GADGET
;
999 else if (strcmp(s
, "datatype")==0)
1000 cl
->classtype
= DATATYPE
;
1001 else if (strcmp(s
, "usbclass")==0)
1002 cl
->classtype
= USBCLASS
;
1003 else if (strcmp(s
, "class")==0)
1004 cl
->classtype
= CLASS
;
1005 else if (strcmp(s
, "hidd")==0)
1006 cl
->classtype
= HIDD
;
1009 fprintf(stderr
, "Unknown type \"%s\" specified\n", s
);
1014 case 26: /* addromtag */
1015 cfg
->addromtag
= strdup(s
);
1018 case 27: /* oopbase_field */
1019 cfg
->oopbase_field
= strdup(s
);
1023 else /* Line starts with ## */
1026 while (isspace(*s
)) s
++;
1027 if (strncmp(s
, "end", 3)!=0)
1028 exitfileerror(20, "\"##end config\" expected\n");
1032 exitfileerror(20, "\"##end config\" expected\n");
1034 while (isspace(*s
)) s
++;
1035 if (strncmp(s
, "config", 6)!=0)
1036 exitfileerror(20, "\"##end config\" expected\n");
1039 while (isspace(*s
)) s
++;
1041 exitfileerror(20, "\"##end config\" expected\n");
1047 /* When not in a class section fill in default values for fields in cfg */
1050 if (cfg
->basename
==NULL
)
1052 cfg
->basename
= strdup(cfg
->modulename
);
1053 *cfg
->basename
= toupper(*cfg
->basename
);
1055 if (cfg
->libbase
==NULL
)
1057 unsigned int len
= strlen(cfg
->basename
)+5;
1058 cfg
->libbase
= malloc(len
);
1059 snprintf(cfg
->libbase
, len
, "%sBase", cfg
->basename
);
1061 if (cfg
->libbasetype
== NULL
&& libbasetypeextern
!= NULL
)
1062 cfg
->libbasetype
= strdup(libbasetypeextern
);
1063 if (cfg
->sysbase_field
!= NULL
&& cfg
->libbasetype
== NULL
)
1064 exitfileerror(20, "sysbase_field specified when no libbasetype is given\n");
1065 if (cfg
->seglist_field
!= NULL
&& cfg
->libbasetype
== NULL
)
1066 exitfileerror(20, "seglist_field specified when no libbasetype is given\n");
1067 if (cfg
->oopbase_field
!= NULL
&& cfg
->libbasetype
== NULL
)
1068 exitfileerror(20, "oopbase_field specified when no libbasetype is given\n");
1069 /* rootbase_field only allowed when duplicating base */
1070 if (cfg
->rootbase_field
!= NULL
&& !(cfg
->options
& OPTION_DUPBASE
))
1071 exitfileerror(20, "rootbasefield only valid for option peropenerbase or pertaskbase\n");
1073 /* Set default date to current date */
1074 if (cfg
->datestring
== NULL
)
1077 time_t now
= time(NULL
);
1078 struct tm
*ltime
= localtime(&now
);
1080 snprintf(tmpbuf
, sizeof(tmpbuf
), "%u.%u.%u",
1081 ltime
->tm_mday
, 1 + ltime
->tm_mon
, 1900 + ltime
->tm_year
);
1083 cfg
->datestring
= strdup(tmpbuf
);
1086 if (cfg
->copyright
== NULL
)
1087 cfg
->copyright
= "";
1089 if ( (cfg
->beginiofunc
!= NULL
&& cfg
->abortiofunc
== NULL
)
1090 || (cfg
->beginiofunc
== NULL
&& cfg
->abortiofunc
!= NULL
)
1092 exitfileerror(20, "please specify both beginio_func and abortio_func\n");
1094 if (libbasetypeextern
==NULL
)
1096 switch (cfg
->modtype
)
1099 cfg
->libbasetypeptrextern
= "struct Device *";
1103 cfg
->libbasetypeptrextern
= "APTR ";
1113 cfg
->libbasetypeptrextern
= "struct Library *";
1116 fprintf(stderr
, "Internal error: Unsupported modtype for libbasetypeptrextern\n");
1122 cfg
->libbasetypeptrextern
= malloc(strlen(libbasetypeextern
)+3);
1123 strcpy(cfg
->libbasetypeptrextern
, libbasetypeextern
);
1124 strcat(cfg
->libbasetypeptrextern
, " *");
1125 free(libbasetypeextern
);
1129 /* When class was given too fill in some defaults when not specified */
1132 if (cl
->classtype
== UNSPECIFIED
)
1133 cl
->classtype
= CLASS
;
1135 if (cl
->basename
== NULL
)
1138 cl
->basename
= cfg
->basename
;
1140 exitfileerror(20, "basename has to be specified in the config section inside of a class section\n");
1143 /* MUI classes are always private */
1144 if (cl
->classtype
== MUI
|| cl
->classtype
== MCC
|| cl
->classtype
== MCP
)
1145 cl
->options
|= COPTION_PRIVATE
;
1147 if (cl
->classid
== NULL
1148 && (cl
->classtype
!= MUI
&& cl
->classtype
!= MCC
&& cl
->classtype
!= MCP
)
1151 if (cl
->classtype
== HIDD
)
1153 cl
->options
&= !COPTION_PRIVATE
;
1155 else if (cl
->options
& COPTION_PRIVATE
)
1157 cl
->classid
= "NULL";
1163 if (cl
->classtype
== GADGET
|| cl
->classtype
== IMAGE
|| cl
->classtype
== CLASS
|| cl
->classtype
== USBCLASS
)
1165 sprintf(s
, "\"%sclass\"", inclass
? cl
->basename
: cfg
->modulename
);
1167 else if (cl
->classtype
== DATATYPE
)
1169 sprintf(s
, "\"%s.datatype\"", inclass
? cl
->basename
: cfg
->modulename
);
1171 cl
->classid
= strdup(s
);
1175 /* Only specify superclass or superclass_field */
1176 if (cl
->superclass
!= NULL
&& cl
->superclass_field
!= NULL
)
1177 exitfileerror(20, "Only specify one of superclass or superclass_field in config section\n");
1179 /* Give default value to superclass if it is not specified */
1180 if (cl
->superclass
== NULL
&& cl
->superclass
== NULL
)
1182 switch (cl
->classtype
)
1186 cl
->superclass
= "MUIC_Area";
1189 cl
->superclass
= "MUIC_Mccprefs";
1192 cl
->superclass
= "IMAGECLASS";
1195 cl
->superclass
= "GADGETCLASS";
1198 cl
->superclass
= "DATATYPESCLASS";
1201 cl
->superclass
= "ROOTCLASS";
1204 cl
->superclass
= "CLID_Root";
1207 exitfileerror(20, "Internal error: unhandled classtype in readsectionconfig\n");
1214 static void readsectioncdef(struct config
*cfg
)
1223 exitfileerror(20, "unexptected end of file in section cdef\n");
1225 if (strncmp(line
, "##", 2)!=0)
1227 slist_append(&cfg
->cdeflines
, line
);
1232 while (isspace(*s
)) s
++;
1233 if (strncmp(s
, "end", 3)!=0)
1234 exitfileerror(20, "\"##end cdef\" expected\n");
1237 while (isspace(*s
)) s
++;
1238 if (strncmp(s
, "cdef", 4)!=0)
1239 exitfileerror(20, "\"##end cdef\" expected\n");
1242 while (isspace(*s
)) s
++;
1244 exitfileerror(20, "unexpected character at position %d\n");
1251 static void readsectioncdefprivate(struct config
*cfg
)
1260 exitfileerror(20, "unexptected end of file in section cdef\n");
1262 if (strncmp(line
, "##", 2)!=0)
1264 slist_append(&cfg
->cdefprivatelines
, line
);
1269 while (isspace(*s
)) s
++;
1270 if (strncmp(s
, "end", 3)!=0)
1271 exitfileerror(20, "\"##end cdefprivate\" expected\n");
1274 while (isspace(*s
)) s
++;
1275 if (strncmp(s
, "cdefprivate", 11)!=0)
1276 exitfileerror(20, "\"##end cdefprivate\" expected\n");
1279 while (isspace(*s
)) s
++;
1281 exitfileerror(20, "unexpected character at position %d\n");
1288 static void readsectionstartup(struct config
*cfg
)
1297 exitfileerror(20, "unexptected end of file in section startup\n");
1299 if (strncmp(line
, "##", 2)!=0)
1301 slist_append(&cfg
->startuplines
, line
);
1306 while (isspace(*s
)) s
++;
1307 if (strncmp(s
, "end", 3)!=0)
1308 exitfileerror(20, "\"##end startup\" expected\n");
1311 while (isspace(*s
)) s
++;
1312 if (strncmp(s
, "startup", 7)!=0)
1313 exitfileerror(20, "\"##end startup\" expected\n");
1316 while (isspace(*s
)) s
++;
1318 exitfileerror(20, "unexpected character at position %d\n");
1325 static void readsectionfunctionlist(struct config
*cfg
)
1328 char *line
, *s
, *s2
;
1329 unsigned int lvo
= cfg
->firstlvo
;
1331 struct functionhead
**funclistptr
= &cfg
->funclist
;
1333 if (cfg
->basename
==NULL
)
1334 exitfileerror(20, "section functionlist has to come after section config\n");
1340 exitfileerror(20, "unexptected EOF in functionlist section\n");
1341 if (strlen(line
)==0)
1343 if (*funclistptr
!= NULL
)
1344 funclistptr
= &((*funclistptr
)->next
);
1347 else if (isspace(*line
))
1350 while (isspace(*s
)) s
++;
1353 if (*funclistptr
!= NULL
)
1354 funclistptr
= &((*funclistptr
)->next
);
1358 exitfileerror(20, "no space allowed before functionname\n");
1360 else if (strncmp(line
, "##", 2)==0)
1363 while (isspace(*s
)) s
++;
1364 if (strncmp(s
, "end", 3)!=0)
1365 exitfileerror(20, "\"##end functionlist\" expected\n");
1368 while (isspace(*s
)) s
++;
1369 if (strncmp(s
, "functionlist", 12)!=0)
1370 exitfileerror(20, "\"##end functionlist\" expected\n");
1373 while (isspace(*s
)) s
++;
1375 exitfileerror(20, "unexpected character on position %d\n", s
-line
);
1379 else if (*line
=='.')
1382 if (strncmp(s
, "skip", 4)==0)
1388 exitfileerror(20, "syntax is '.skip n'\n");
1390 n
=strtol(s
, &s2
, 10);
1392 exitfileerror(20, "positive number expected\n");
1394 while (isspace(*s2
)) s2
++;
1395 if ((*s2
!= '\0') && (*s2
!= '#'))
1396 exitfileerror(20, "syntax is '.skip n'\n");
1397 if (*funclistptr
!= NULL
)
1398 funclistptr
= &((*funclistptr
)->next
);
1401 else if (strncmp(s
, "alias", 5)==0)
1406 exitfileerror(20, "syntax is '.alias name'\n");
1408 while (isspace(*s
)) s
++;
1409 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1410 exitfileerror(20, "syntax is '.alias name'\n");
1414 while (isalnum(*s
) || *s
== '_') s
++;
1421 } while (isspace(*s
));
1425 exitfileerror(20, "syntax is '.alias name'\n");
1427 if (*funclistptr
== NULL
)
1428 exitfileerror(20, ".alias has to come after a function declaration\n");
1430 slist_append(&(*funclistptr
)->aliases
, s2
);
1432 else if (strncmp(s
, "function", 8) == 0)
1437 exitfileerror(20, "Syntax error\n");
1439 while (isspace(*s
)) s
++;
1440 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1441 exitfileerror(20, "syntax is '.function name'\n");
1445 while (isalnum(*s
) || *s
== '_') s
++;
1452 } while (isspace(*s
));
1456 exitfileerror(20, "syntax is '.function name'\n");
1458 if (*funclistptr
== NULL
)
1459 exitfileerror(20, ".function has to come after a function declaration\n");
1461 funcsetinternalname(*funclistptr
, s2
);
1463 else if (strncmp(s
, "cfunction", 9)==0)
1465 if (*funclistptr
== NULL
)
1466 exitfileerror(20, ".cfunction has to come after a function declaration\n");
1468 (*funclistptr
)->libcall
= REGISTER
;
1470 else if (strncmp(s
, "private", 7)==0)
1472 if (*funclistptr
== NULL
)
1473 exitfileerror(20, ".private has to come after a function declaration\n");
1475 (*funclistptr
)->priv
= 1;
1477 else if (strncmp(s
, "novararg", 8)==0)
1479 if (*funclistptr
== NULL
)
1480 exitfileerror(20, ".novararg has to come after a function declaration\n");
1482 (*funclistptr
)->novararg
= 1;
1484 else if (strncmp(s
, "version", 7) == 0)
1486 /* Mark version number for the following
1487 * functions, so that the automatic OpenLibrary()
1488 * will know what version to use.
1495 while (isspace(*s
)) s
++;
1496 ver
= (int)strtol(s
, &tmp
, 0);
1499 exitfileerror(20, ".version expects an integer\n");
1502 while (isspace(*s
)) s
++;
1504 if (*s
&& *s
!= '#')
1505 exitfileerror(20, ".version has junk after the version number\n");
1510 exitfileerror(20, "Syntax error");
1512 else if (*line
!='#') /* Ignore line that is a comment, e.g. that starts with a # */
1514 /* The line is a function prototype. It can have two syntax
1515 * type funcname(argproto1, argproto2, ...)
1516 * type funcname(argproto1, argproto2, ...) (reg1, reg2, ...)
1517 * The former is for C type function argument passing, the latter for
1518 * register argument passing.
1520 char c
, *args
[64], *regs
[64], *funcname
;
1521 int len
, argcount
= 0, regcount
= 0, brcount
= 0;
1523 /* Parse 'type functionname' at the beginning of the line */
1524 s
= strchr(line
, '(');
1526 exitfileerror(20, "( expected at position %d\n", strlen(line
) + 1);
1529 while (isspace(*(s2
-1)))
1533 while (s2
> line
&& !isspace(*(s2
-1)) && !(*(s2
-1) == '*'))
1537 exitfileerror(20, "No type specifier before function name\n");
1539 if (*funclistptr
!= NULL
)
1540 funclistptr
= &((*funclistptr
)->next
);
1541 *funclistptr
= newfunctionhead(s2
, STACK
);
1543 while (isspace(*(s2
-1)))
1546 (*funclistptr
)->type
= strdup(line
);
1547 (*funclistptr
)->lvo
= lvo
;
1548 (*funclistptr
)->version
= minversion
;
1551 /* Parse function prototype */
1568 && !(brcount
== 0 && (*s
== ',' || *s
== ')'))
1578 exitfileerror(20, "Unexected ')' at position %d\n", s
-line
+1);
1585 exitfileerror(20, "'(' without ')'");
1588 while (isspace(*(s2
-1)))
1592 if (!(s2
> args
[argcount
- 1]))
1593 exitfileerror(20, "Syntax error in function prototype\n");
1599 while (*s
!= '\0' && isspace(*s
))
1604 /* Parse registers specifications if available otherwise this prototype for C type argument passing */
1606 /* There may be no register specified with () so be sure then c is == ')' */
1621 if (memchr("AD",s
[0],2)!=NULL
&& memchr("01234567",s
[1],8)!=NULL
)
1628 if (s
[0] == s
[-3] && s
[1] == s
[-2] + 1)
1635 "wrong register specification \"%s\" for argument %u\n",
1636 regs
[regcount
-1], regcount
1640 exitfileerror(20, "maximum four arguments passed in two registers allowed (%d, %s) \n", regcount
, regs
[regcount
-1]);
1646 "wrong register \"%s\" for argument %u\n",
1647 regs
[regcount
-1], regcount
1656 exitfileerror(20, "'(' without ')'\n");
1657 if (c
!= ',' && c
!= ')')
1658 exitfileerror(20, "',' or ')' expected at position %d\n", s
-line
+1);
1664 while (isspace(*s
)) s
++;
1666 exitfileerror(20, "wrong char '%c' at position %d\n", *s
, (int)(s
-line
) + 1);
1668 if (argcount
!= regcount
)
1669 exitfileerror(20, "Number of arguments (%d) and registers (%d) mismatch\n",
1673 (*funclistptr
)->libcall
= REGISTERMACRO
;
1674 for (i
= 0; i
< argcount
; i
++)
1675 funcaddarg(*funclistptr
, args
[i
], regs
[i
]);
1677 else if (*s
== '\0')
1678 { /* No registers specified */
1679 for (i
= 0; i
< argcount
; i
++)
1680 funcaddarg(*funclistptr
, args
[i
], NULL
);
1683 exitfileerror(20, "wrong char '%c' at position %d\n", *s
, (int)(s
-line
) + 1);
1688 static void readsectionmethodlist(struct classinfo
*cl
)
1691 char *line
, *s
, *s2
;
1692 struct functionhead
**methlistptr
= &cl
->methlist
;
1693 struct stringlist
*interface
= NULL
;
1695 if (cl
->basename
==NULL
)
1696 exitfileerror(20, "section methodlist has to come after section config\n");
1702 exitfileerror(20, "unexptected EOF in methodlist section\n");
1704 /* Ignore empty lines or lines that qre a comment, e.g. that starts with a # */
1705 if (strlen(line
)==0 || (line
[0] == '#' && line
[1] != '#'))
1709 exitfileerror(20, "No space allowed at start of the line\n");
1711 if (strncmp(line
, "##", 2)==0) /* Is this the end ? */
1714 while (isspace(*s
)) s
++;
1715 if (strncmp(s
, "end", 3)!=0)
1716 exitfileerror(20, "\"##end methodlist\" expected\n");
1719 while (isspace(*s
)) s
++;
1720 if (strncmp(s
, "methodlist", 10)!=0)
1721 exitfileerror(20, "\"##end methodlist\" expected\n");
1724 while (isspace(*s
)) s
++;
1726 exitfileerror(20, "unexpected character on position %d\n", s
-line
);
1736 if (strncmp(s
, "alias", 5)==0)
1741 exitfileerror(20, "syntax is '.alias name'\n");
1743 while (isspace(*s
)) s
++;
1744 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1745 exitfileerror(20, "syntax is '.alias name'\n");
1749 while (isalnum(*s
) || *s
== '_') s
++;
1756 } while (isspace(*s
));
1760 exitfileerror(20, "syntax is '.alias name'\n");
1762 if (*methlistptr
== NULL
)
1763 exitfileerror(20, ".alias has to come after a function declaration\n");
1765 slist_append(&(*methlistptr
)->aliases
, s2
);
1767 else if (strncmp(s
, "function", 8) == 0)
1772 exitfileerror(20, "Syntax error\n");
1774 while (isspace(*s
)) s
++;
1775 if (*s
== '\0' || !(isalpha(*s
) || *s
== '_'))
1776 exitfileerror(20, "syntax is '.function name'\n");
1780 while (isalnum(*s
) || *s
== '_') s
++;
1787 } while (isspace(*s
));
1791 exitfileerror(20, "syntax is '.function name'\n");
1793 if (*methlistptr
== NULL
)
1794 exitfileerror(20, ".function has to come after a function declaration\n");
1796 funcsetinternalname(*methlistptr
, s2
);
1798 else if (strncmp(s
, "interface", 9) == 0)
1800 if (cl
->classtype
!= HIDD
)
1801 exitfileerror(20, "interface only valid for a HIDD\n");
1806 exitfileerror(20, "Syntax error\n");
1808 while (isspace(*s
)) s
++;
1809 if (*s
== '\0' || !isalpha(*s
))
1810 exitfileerror(20, "syntax is '.interface name'\n");
1814 while (isalnum(*s
) || *s
== '_') s
++;
1821 } while (isspace(*s
));
1825 exitfileerror(20, "syntax is '.interface name'\n");
1827 interface
= slist_append(&cl
->interfaces
, s2
);
1830 exitfileerror(20, "Syntax error");
1832 else if (isalpha(*line
))
1836 for (s
= line
+ 1; isalnum(*s
) || *s
== '_'; s
++)
1839 if (cl
->classtype
== HIDD
&& interface
== NULL
)
1840 exitfileerror(20, "For a HIDD the first method has to come after an .interface line\n");
1843 exitfileerror(20, "Only letters, digits and an underscore allowed in a methodname\n");
1845 if (*methlistptr
!= NULL
)
1846 methlistptr
= &((*methlistptr
)->next
);
1847 if (cl
->classtype
!= HIDD
)
1849 if (snprintf(stmp
, 256, "%s__%s", cl
->basename
, line
) >= 256)
1850 exitfileerror(20, "Method name too large\n");
1852 *methlistptr
= newfunctionhead(stmp
, STACK
);
1853 (*methlistptr
)->type
= "IPTR";
1854 funcaddarg(*methlistptr
, "Class *cl", NULL
);
1855 funcaddarg(*methlistptr
, "Object *o", NULL
);
1856 funcaddarg(*methlistptr
, "Msg msg", NULL
);
1860 if (snprintf(stmp
, 256, "%s__%s__%s", cl
->basename
, interface
->s
, line
) >= 256)
1861 exitfileerror(20, "Method name too large\n");
1863 *methlistptr
= newfunctionhead(stmp
, STACK
);
1864 (*methlistptr
)->type
= "IPTR";
1865 funcaddarg(*methlistptr
, "OOP_Class *cl", NULL
);
1866 funcaddarg(*methlistptr
, "OOP_Object *o", NULL
);
1867 funcaddarg(*methlistptr
, "OOP_Msg msg", NULL
);
1868 (*methlistptr
)->interface
= interface
;
1869 if (snprintf(stmp
, 256, "mo%s_%s", interface
->s
, line
) >= 256)
1870 exitfileerror(20, "Method name too large\n");
1871 (*methlistptr
)->method
= strdup(stmp
);
1873 slist_append(&(*methlistptr
)->aliases
, line
);
1876 exitfileerror(20, "Methodname has to begin with a letter\n");
1881 readsectionclass(struct config
*cfg
)
1884 struct classinfo
*cl
;
1887 s
= readsections(cfg
, cl
, 1);
1889 exitfileerror(20, "Unexpected end of file\n");
1891 if (strncmp(s
, "##", 2) != 0)
1892 exitfileerror(20, "'##end class' expected\n");
1895 while (isspace(*s
)) s
++;
1897 if (strncmp(s
, "end", 3) != 0)
1898 exitfileerror(20, "'##end class' expected\n");
1902 exitfileerror(20, "'##end class' expected\n");
1903 while (isspace(*s
)) s
++;
1905 if (strncmp(s
, "class", 5) != 0)
1906 exitfileerror(20, "'##end class' expected\n");
1909 while (isspace(*s
)) s
++;
1911 exitfileerror(20, "'##end class' expected\n");
1914 static struct classinfo
*newclass(struct config
*cfg
)
1916 struct classinfo
*cl
, *classlistit
;
1918 cl
= malloc(sizeof(struct classinfo
));
1921 fprintf(stderr
, "Out of memory\n");
1924 memset(cl
, 0, sizeof(struct classinfo
));
1926 /* By default the classes are initialized with a priority of 1 so they
1927 * are initialized before any user added initialization with priority 1
1931 if (cfg
->classlist
== NULL
)
1932 cfg
->classlist
= cl
;
1937 classlistit
= cfg
->classlist
;
1938 classlistit
->next
!= NULL
;
1939 classlistit
= classlistit
->next
1942 classlistit
->next
= cl
;
1948 static struct handlerinfo
*newhandler(struct config
*cfg
)
1950 struct handlerinfo
*hl
;
1952 hl
= calloc(1,sizeof(*hl
));
1953 hl
->next
= cfg
->handlerlist
;
1954 cfg
->handlerlist
= hl
;
1958 static int getdirective(char *s
, const char *directive
, int range_min
, int range_max
, int *val
)
1963 if (strncmp(s
, directive
, strlen(directive
)) != 0)
1966 s
+= strlen(directive
);
1967 if (*s
&& !isspace(*s
))
1968 exitfileerror(20, "Unrecognized directive \".%s\"\n", directive
);
1970 while (isspace(*s
)) s
++;
1972 exitfileerror(20, "No .%s value specified\n", directive
);
1974 newval
= strtol(s
, &tmp
, 0);
1975 if (s
== tmp
|| !(newval
>= range_min
&& newval
<= range_max
)) {
1977 while (*tmp
&& !isspace(*tmp
)) tmp
++;
1978 exitfileerror(20, "Invalid .%s value of %.*s\n", directive
, tmp
- s
, s
);
1986 readsectionhandler(struct config
*cfg
)
1988 char *line
= NULL
, *s
;
1989 struct handlerinfo
*hl
;
1990 unsigned char autolevel
= 0;
1991 unsigned int stacksize
;
2004 s
= line
= readline();
2007 exitfileerror(20, "unexpected end of file in section hanlder\n");
2009 if (strncmp(s
, "##", 2)==0)
2012 /* Ignore comments */
2013 if (strncmp(s
, "#", 1)==0)
2016 /* Skip ahead to function name */
2017 while (*s
&& isspace(*s
)) s
++;
2019 /* Permit blank lines */
2027 if (getdirective(s
, "autodetect", 0, 127, &val
)) {
2029 } else if (getdirective(s
, "stacksize", 0, INT_MAX
, &val
)) {
2031 } else if (getdirective(s
, "priority", -128, 127, &val
)) {
2034 exitfileerror(20, "Unrecognized directive \"%s\"\n", line
);
2040 while (*s
&& !isspace(*s
)) s
++;
2041 function_len
= s
- function
;
2044 exitfileerror(20, "No identifier specified for the handler");
2046 function
[function_len
] = 0;
2050 unsigned int id
= 0;
2052 if (strncasecmp(s
,"resident=",9)==0) {
2055 s
= strchr(s
, '=') + 1;
2057 while (*s
&& !isspace(*s
)) s
++;
2059 exitfileerror(20, "Empty resident= is not permitted\n");
2064 hl
= newhandler(cfg
);
2065 hl
->type
= HANDLER_RESIDENT
;
2067 hl
->name
= strdup(res
);
2068 hl
->autodetect
= autolevel
--;
2069 hl
->stacksize
= stacksize
;
2070 hl
->priority
= priority
;
2071 hl
->handler
= strdup(function
);
2072 } else if (strncasecmp(s
,"dosnode=",8)==0) {
2075 s
= strchr(s
, '=') + 1;
2077 while (*s
&& !isspace(*s
)) s
++;
2079 exitfileerror(20, "Empty dosnode= is not permitted\n");
2084 hl
= newhandler(cfg
);
2085 hl
->type
= HANDLER_DOSNODE
;
2087 hl
->name
= strdup(dev
);
2088 hl
->autodetect
= autolevel
? autolevel
-- : 0;
2089 hl
->handler
= strdup(function
);
2090 hl
->stacksize
= stacksize
;
2091 hl
->priority
= priority
;
2092 } else if (strncasecmp(s
,"dostype=",8) == 0) {
2093 s
= strchr(s
, '=') + 1;
2095 id
= (unsigned int)strtoul(s
, &tmp
, 0);
2098 while (*tmp
&& !isspace(*tmp
))
2100 exitfileerror(20, "\"%.*s\" is not a numerical DOS ID\n", (tmp
-s
), s
);
2104 if (id
== 0 || id
== ~0) {
2105 exitfileerror(20, "DOS ID 0x%08x is not permitted\n", id
);
2108 hl
= newhandler(cfg
);
2109 hl
->type
= HANDLER_DOSTYPE
;
2112 hl
->autodetect
= autolevel
? autolevel
-- : 0;
2113 hl
->handler
= strdup(function
);
2114 hl
->stacksize
= stacksize
;
2115 hl
->priority
= priority
;
2117 for (tmp
= s
; !isspace(*tmp
); tmp
++);
2118 exitfileerror(20, "Unknown option \"%.*s\"\n", tmp
- s
, s
);
2121 /* Advance to next ID */
2122 while (*s
&& isspace(*s
)) s
++;
2128 exitfileerror(20, "Unexpected end of file\n");
2130 if (strncmp(s
, "##", 2) != 0)
2131 exitfileerror(20, "'##end handler' expected\n");
2134 while (isspace(*s
)) s
++;
2136 if (strncmp(s
, "end", 3) != 0)
2137 exitfileerror(20, "'##end handler' expected\n");
2140 while (isspace(*s
)) s
++;
2142 if (strncmp(s
, "handler", 7) != 0)
2143 exitfileerror(20, "'##end handler' expected\n");
2146 while (isspace(*s
)) s
++;
2148 exitfileerror(20, "'##end handler' expected\n");