Added startup section to library .conf file. Code in this section will be
[AROS.git] / tools / genmodule / config.c
blob792aeb77993e7983d67d2addd36b074e19bd256d
1 /*
2 Copyright © 1995-2009, The AROS Development Team. All rights reserved.
3 $Id$
5 Code to parse the command line options and the module config file for
6 the genmodule program
7 */
9 #include <string.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <time.h>
13 #include <unistd.h>
15 #include "functionhead.h"
16 #include "config.h"
18 const static char bannertemplate[] =
19 "/*\n"
20 " *** Automatically generated from '%s'. Edits will be lost. ***\n"
21 " Copyright © 1995-2009, The AROS Development Team. All rights reserved.\n"
22 "*/\n";
24 const char*
25 getBanner(struct config* config)
27 int bannerlength = strlen(config->conffile) + strlen(bannertemplate) -1;
28 char * banner = malloc(bannerlength);
30 snprintf (banner, bannerlength, bannertemplate, config->conffile);
32 return(banner);
35 void
36 freeBanner(char *banner)
38 free((void *)banner);
41 const static char usage[] =
42 "\n"
43 "Usage: genmodule [-c conffile] [-s suffix] [-d gendir] [-r reffile] [-n]\n"
44 " {writefiles|writemakefile|writeincludes|writedummy|writelibdefs|writefunclist} modname modtype\n"
47 static void readconfig(struct config *);
48 static struct classinfo *newclass(struct config *);
50 /* the method prefices for the supported classes */
51 static const char *muimprefix[] =
53 "__OM_",
54 "__MUIM_",
55 NULL
57 static const char *gadgetmprefix[] =
59 "__OM_",
60 "__GM_",
61 "__AROSM_",
62 NULL
64 static const char *dtmprefix[] =
66 "__OM_",
67 "__GM_",
68 "__DTM_",
69 "__PDTM_",
70 NULL
73 /* Create a config struct. Initialize with the values from the programs command
74 * line arguments and the contents of the modules .conf file
76 struct config *initconfig(int argc, char **argv)
78 struct config *cfg;
79 char *s, **argvit = argv + 1;
80 int hassuffix = 0, c;
82 cfg = malloc(sizeof(struct config));
83 if (cfg == NULL)
85 fprintf(stderr, "Out of memory\n");
86 exit(20);
89 memset(cfg, 0, sizeof(struct config));
91 while ((c = getopt(argc, argv, ":c:s:d:r:")) != -1)
93 if (c == ':')
95 fprintf(stderr, "Option -%c needs an argument\n",optopt);
96 exit(20);
99 switch (c)
101 case 'c':
102 cfg->conffile = optarg;
103 break;
104 case 's':
105 cfg->suffix = optarg;
106 hassuffix = 1;
107 break;
108 case 'd':
109 /* Remove / at end if present */
110 if ((optarg)[strlen(*argvit)-1]=='/') (optarg)[strlen(optarg)-1]='\0';
111 cfg->gendir = optarg;
112 break;
113 case 'r':
114 cfg->reffile = optarg;
115 break;
116 default:
117 fprintf(stderr, "Internal error: Unhandled option\n");
118 exit(20);
122 if (optind + 3 != argc)
124 fprintf(stderr, "Wrong number of arguments.\n%s", usage);
125 exit(20);
128 if (strcmp(argv[optind], "writefiles") == 0)
130 cfg->command = FILES;
132 else if (strcmp(argv[optind], "writemakefile") == 0)
134 cfg->command = MAKEFILE;
136 else if (strcmp(argv[optind], "writeincludes") == 0)
138 cfg->command = INCLUDES;
140 else if (strcmp(argv[optind], "writelibdefs") == 0)
142 cfg->command = LIBDEFS;
144 else if (strcmp(argv[optind], "writedummy") == 0)
146 cfg->command = DUMMY;
148 else if (strcmp(argv[optind], "writefunclist") == 0)
150 cfg->command = WRITEFUNCLIST;
152 else
154 fprintf(stderr, "Unrecognized argument \"%s\"\n%s", argv[optind], usage);
155 exit(20);
158 cfg->modulename = argv[optind+1];
159 cfg->modulenameupper = strdup(cfg->modulename);
160 for (s=cfg->modulenameupper; *s!='\0'; *s = toupper(*s), s++)
163 if (strcmp(argv[optind+2],"library")==0)
165 cfg->modtype = LIBRARY;
166 cfg->moddir = "Libs";
168 else if (strcmp(argv[optind+2],"mcc")==0)
170 cfg->modtype = MCC;
171 cfg->moddir = "Classes/Zune";
173 else if (strcmp(argv[optind+2],"mui")==0)
175 cfg->modtype = MUI;
176 cfg->moddir = "Classes/Zune";
178 else if (strcmp(argv[optind+2],"mcp")==0)
180 cfg->modtype = MCP;
181 cfg->moddir = "Classes/Zune";
183 else if (strcmp(argv[optind+2], "device")==0)
185 cfg->modtype = DEVICE;
186 cfg->moddir = "Devs";
188 else if (strcmp(argv[optind+2], "resource")==0)
190 cfg->modtype = RESOURCE;
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], "usbclass")==0)
205 cfg->modtype = USBCLASS;
206 cfg->moddir = "Classes/USB";
207 if(!hassuffix)
209 cfg->suffix = "class";
210 hassuffix = 1;
213 else if (strcmp(argv[optind+2], "hidd")==0)
215 cfg->modtype = HIDD;
216 cfg->moddir = "Devs/Drivers";
218 else
220 fprintf(stderr, "Unknown modtype \"%s\" specified for second argument\n", argv[2]);
221 exit(20);
224 if (!hassuffix)
225 cfg->suffix = argv[optind+2];
227 /* Fill fields with default value if not specified on the command line */
229 char tmpbuf[256];
231 if (cfg->conffile == NULL)
233 snprintf(tmpbuf, sizeof(tmpbuf), "%s.conf", cfg->modulename);
234 cfg->conffile = strdup(tmpbuf);
237 if (cfg->gendir == NULL)
238 cfg->gendir = ".";
240 if (cfg->command != FILES && cfg->command != INCLUDES && cfg->command != WRITEFUNCLIST)
242 if (cfg->reffile != NULL)
243 fprintf(stderr, "WARNING ! Option -r ingored for %s\n", argv[optind]);
245 else if (cfg->command == FILES && cfg->reffile == NULL)
247 snprintf(tmpbuf, sizeof(tmpbuf), "%s.ref", cfg->modulename);
248 cfg->reffile = strdup(tmpbuf);
252 readconfig(cfg);
254 /* For a device add the functions given in beginiofunc and abortiofunc to the functionlist
255 * if they are provided
257 if (cfg->beginiofunc != NULL)
259 struct functionhead *funchead;
261 cfg->intcfg |= CFG_NOREADREF;
263 /* Add beginio_func to the list of functions */
264 funchead = newfunctionhead(cfg->beginiofunc, REGISTERMACRO);
265 funchead->type = strdup("void");
266 funchead->lvo = 5;
267 funcaddarg(funchead, "struct IORequest *ioreq", "A1");
269 funchead->next = cfg->funclist;
270 cfg->funclist = funchead;
272 /* Add abortio_func to the list of functions */
273 funchead = newfunctionhead(cfg->abortiofunc, REGISTERMACRO);
274 funchead->type = strdup("LONG");
275 funchead->lvo = 6;
276 funcaddarg(funchead, "struct IORequest *ioreq", "A1");
278 funchead->next = cfg->funclist->next;
279 cfg->funclist->next = funchead;
281 else if (cfg->modtype == DEVICE && cfg->intcfg & CFG_NOREADREF)
283 fprintf
285 stderr,
286 "beginio_func and abortio_func missing for a device with a non empty function list\n"
288 exit(20);
291 return cfg;
294 /* Functions to read configuration from the configuration file */
296 #include "fileread.h"
298 static char *readsections(struct config *, struct classinfo *, int);
299 static void readsectionconfig(struct config *, struct classinfo *, int);
300 static void readsectioncdef(struct config *);
301 static void readsectioncdefprivate(struct config *);
302 static void readsectionstartup(struct config *);
303 static void readsectionfunctionlist(struct config *);
304 static void readsectionmethodlist(struct classinfo *);
305 static void readsectionclass(struct config *);
307 static void readconfig(struct config *cfg)
309 struct classinfo *mainclass = NULL;
311 /* Create a classinfo structure if this module is a class */
312 switch (cfg->modtype)
314 case LIBRARY:
315 case DEVICE:
316 case RESOURCE:
317 case USBCLASS:
318 break;
320 case MCC:
321 case MUI:
322 case MCP:
323 case GADGET:
324 case DATATYPE:
325 case HIDD:
326 mainclass = newclass(cfg);
327 mainclass->classtype = cfg->modtype;
328 break;
330 default:
331 fprintf(stderr, "Internal error: unsupported modtype for classinfo creation\n");
332 exit(20);
335 switch (cfg->modtype)
337 case LIBRARY:
338 case USBCLASS:
339 cfg->firstlvo = 5;
340 break;
341 case DEVICE:
342 cfg->firstlvo = 7;
343 break;
344 case MCC:
345 case MUI:
346 case MCP:
347 cfg->firstlvo = 6;
348 mainclass->boopsimprefix = muimprefix;
349 break;
350 case RESOURCE:
351 cfg->firstlvo = 1;
352 break;
353 case GADGET:
354 cfg->firstlvo = 5;
355 mainclass->boopsimprefix = gadgetmprefix;
356 break;
357 case DATATYPE:
358 cfg->firstlvo = 6;
359 mainclass->boopsimprefix = dtmprefix;
360 break;
361 case HIDD:
362 cfg->firstlvo = 5;
363 /* FIXME: need boopsimprefix ? */
364 break;
365 default:
366 fprintf(stderr, "Internal error: unsupported modtype for firstlvo\n");
367 exit(20);
370 if (!fileopen(cfg->conffile))
372 fprintf(stderr, "In readconfig: Could not open %s\n", cfg->conffile);
373 exit(20);
376 /* Read all sections and see that we are at the end of the file */
377 if (readsections(cfg, mainclass, 0) != NULL)
378 exitfileerror(20, "Syntax error");
380 fileclose();
383 /* readsections will scan through all the sections in the config file.
384 * arguments:
385 * struct config *cfg: The module config data which may be updated by
386 * the information in the sections
387 * struct classinfo *cl: The classdata to be filled with data from the sections.
388 * This may be NULL if this is the main part of the configuration file and the
389 * type of the module is not a class
390 * int inclass: Boolean to indicate if we are in a class part. If not we are in the main
391 * part of the config file.
393 static char *readsections(struct config *cfg, struct classinfo *cl, int inclass)
395 char *line, *s, *s2;
396 int hasconfig = 0;
398 while ((line=readline())!=NULL)
400 if (strncmp(line, "##", 2)==0)
402 static char *parts[] =
404 "config", "cdefprivate", "cdef", "startup", "functionlist", "methodlist", "class"
406 const unsigned int nums = sizeof(parts)/sizeof(char *);
407 unsigned int partnum;
408 int i, atend = 0;
410 s = line+2;
411 while (isspace(*s)) s++;
413 if (strncmp(s, "begin", 5)!=0)
414 return line;
416 s += 5;
417 if (!isspace(*s))
418 exitfileerror(20, "space after begin expected\n");
419 while (isspace(*s)) s++;
421 for (i = 0, partnum = 0; partnum==0 && i<nums; i++)
423 if (strncmp(s, parts[i], strlen(parts[i]))==0)
425 partnum = i+1;
426 s += strlen(parts[i]);
427 while (isspace(*s)) s++;
428 if (*s!='\0')
429 exitfileerror(20, "unexpected character on position %d\n", s-line);
432 if (partnum==0)
433 exitfileerror(20, "unknown start of section\n");
434 switch (partnum)
436 case 1: /* config */
437 readsectionconfig(cfg, cl, inclass);
438 hasconfig = 1;
439 break;
441 case 2: /* cdefprivate */
442 if (inclass)
443 exitfileerror(20, "cdefprivate section not allowed in class section\n");
444 readsectioncdefprivate(cfg);
445 break;
447 case 3: /* cdef */
448 if (inclass)
449 exitfileerror(20, "cdef section not allowed in class section\n");
450 readsectioncdef(cfg);
451 break;
453 case 4: /* startup */
454 if (inclass)
455 exitfileerror(20, "startup section not allowed in class section\n");
456 readsectionstartup(cfg);
457 break;
459 case 5: /* functionlist */
460 if (inclass)
461 exitfileerror(20, "functionlist section not allow in class section\n");
462 readsectionfunctionlist(cfg);
463 cfg->intcfg |= CFG_NOREADREF;
464 break;
466 case 6: /* methodlist */
467 if (cl == NULL)
468 exitfileerror(20, "methodlist section when not in a class\n");
469 readsectionmethodlist(cl);
470 cfg->intcfg |= CFG_NOREADREF;
471 break;
473 case 7: /* class */
474 if (inclass)
475 exitfileerror(20, "class section may not be nested\n");
476 readsectionclass(cfg);
477 break;
480 else if (strlen(line)!=0)
481 filewarning("warning line outside section ignored\n");
484 if(!inclass)
486 if (!hasconfig)
487 exitfileerror(20, "No config section in conffile\n");
489 /* If no indication was given for generating includes or not
490 decide on module type and if there are functions
492 if(!((cfg->options & OPTION_INCLUDES) || (cfg->options & OPTION_NOINCLUDES)))
494 switch (cfg->modtype)
496 case LIBRARY:
497 case RESOURCE:
498 case USBCLASS:
499 cfg->options |= OPTION_INCLUDES;
500 break;
502 case DEVICE:
503 cfg->options |= (
504 (cfg->funclist != NULL)
505 || (cfg->cdeflines != NULL)
506 || strcmp(cfg->libbasetypeptrextern, "struct Device *") != 0
507 ) ? OPTION_INCLUDES : OPTION_NOINCLUDES;
508 break;
510 case GADGET:
511 case DATATYPE:
512 case MCC:
513 case MUI:
514 case MCP:
515 case HIDD:
516 cfg->options |= (
517 (cfg->funclist != NULL)
518 || (cfg->cdeflines != NULL)
519 ) ? OPTION_INCLUDES : OPTION_NOINCLUDES;
520 break;
522 default:
523 fprintf(stderr, "Internal error writemakefile: unhandled modtype for includes\n");
524 exit(20);
525 break;
529 /* If no indication was given for not generating stubs only generate them if
530 * the module has functions
532 if(!((cfg->options & OPTION_STUBS) || (cfg->options & OPTION_NOSTUBS)))
534 cfg->options |= (cfg->funclist != NULL) ?
535 OPTION_STUBS : OPTION_NOSTUBS;
538 /* If no indication was given for generating autoinit code or not
539 decide on module type
541 if(!((cfg->options & OPTION_AUTOINIT) || (cfg->options & OPTION_NOAUTOINIT)))
543 switch (cfg->modtype)
545 case LIBRARY:
546 case USBCLASS:
547 cfg->options |= OPTION_AUTOINIT;
548 break;
550 case RESOURCE:
551 case GADGET:
552 case DEVICE:
553 case DATATYPE:
554 case MCC:
555 case MUI:
556 case MCP:
557 case HIDD:
558 cfg->options |= OPTION_NOAUTOINIT;
559 break;
561 default:
562 fprintf(stderr, "Internal error writemakefile: unhandled modtype for autoinit\n");
563 exit(20);
564 break;
568 return NULL;
571 static void readsectionconfig(struct config *cfg, struct classinfo *cl, int inclass)
573 int atend = 0, i;
574 char *line, *s, *s2, *libbasetypeextern = NULL;
575 struct tm date;
577 while (!atend)
579 line = readline();
580 if (line==NULL)
581 exitfileerror(20, "unexpected end of file in section config\n");
583 if (strncmp(line, "##", 2)!=0)
585 const char *names[] =
587 "basename", "libbase", "libbasetype", "libbasetypeextern",
588 "version", "date", "copyright", "libcall", "forcebase", "superclass",
589 "superclass_field", "residentpri", "options", "sysbase_field",
590 "seglist_field", "rootbase_field", "classptr_field", "classptr_var",
591 "classid", "classdatatype", "beginio_func", "abortio_func", "dispatcher",
592 "initpri", "type", "getidfunc"
594 const unsigned int namenums = sizeof(names)/sizeof(char *);
595 unsigned int namenum;
597 for (i = 0, namenum = 0; namenum==0 && i<namenums; i++)
601 strncmp(line, names[i], strlen(names[i]))==0
602 && isspace(*(line+strlen(names[i])))
604 namenum = i+1;
606 if (namenum==0)
607 exitfileerror(20, "unrecognized configuration option\n");
609 s = line + strlen(names[namenum-1]);
610 if (!isspace(*s))
611 exitfileerror(20, "space character expected after \"%s\"\n", names[namenum-1]);
613 while (isspace(*s)) s++;
614 if (*s=='\0')
615 exitfileerror(20, "unexpected end of line\n");
617 s2 = s + strlen(s);
618 while (isspace(*(s2-1))) s2--;
619 *s2 = '\0';
621 switch (namenum)
623 case 1: /* basename */
624 if (!inclass)
625 cfg->basename = strdup(s);
626 if (cl != NULL)
627 cl->basename = strdup(s);
628 break;
630 case 2: /* libbase */
631 if (inclass)
632 exitfileerror(20, "libbase not valid config option when in a class section\n");
633 cfg->libbase = strdup(s);
634 break;
636 case 3: /* libbasetype */
637 if (inclass)
638 exitfileerror(20, "libbasetype not valid config option when in a class section\n");
639 cfg->libbasetype = strdup(s);
640 break;
642 case 4: /* libbasetypeextern */
643 if (inclass)
644 exitfileerror(20, "libbasetype not valid config option when in a class section\n");
645 libbasetypeextern = strdup(s);
646 break;
648 case 5: /* version */
649 if (inclass)
650 exitfileerror(20, "version not valid config option when in a class section\n");
651 if (sscanf(s, "%u.%u", &cfg->majorversion, &cfg->minorversion)!=2)
652 exitfileerror(20, "wrong version string \"%s\"\n", s);
653 break;
655 case 6: /* date */
656 if (inclass)
657 exitfileerror(20, "date not valid config option when in a class section\n");
658 if (strptime(s, "%e.%m.%Y", &date) == NULL)
660 exitfileerror(20, "date string has to have d.m.yyyy format\n");
662 cfg->datestring = strdup(s);
663 break;
665 case 7: /* copyright */
666 if (inclass)
667 exitfileerror(20, "copyright not valid config option when in a class section\n");
668 cfg->copyright = strdup(s);
669 break;
671 case 8: /* libcall */
672 fprintf(stderr, "libcall specification is deprecated and ignored\n");
673 break;
675 case 9: /* forcebase */
676 if (inclass)
677 exitfileerror(20, "forcebase not valid config option when in a class section\n");
678 slist_append(&cfg->forcelist, s);
679 break;
681 case 10: /* superclass */
682 if (cl == NULL)
683 exitfileerror(20, "superclass specified when not a BOOPSI class\n");
684 cl->superclass = strdup(s);
685 break;
687 case 11: /* superclass_field */
688 if (cl == NULL)
689 exitfileerror(20, "superclass_field specified when not a BOOPSI class\n");
690 cl->superclass_field = strdup(s);
691 break;
693 case 12: /* residentpri */
694 if (!inclass)
696 int count;
697 char dummy;
699 count = sscanf(s, "%d%c", &cfg->residentpri, &dummy);
700 if (count != 1 ||
701 cfg->residentpri < -128 || cfg->residentpri > 127
704 exitfileerror(20, "residentpri number format error\n");
707 else
708 exitfileerror(20, "residentpri not valid config option when in a class section\n");
709 break;
711 case 13: /* options */
712 if (!inclass)
714 static const char *optionnames[] =
716 "noautolib", "noexpunge", "noresident", "peropenerbase",
717 "peridbase", "includes", "noincludes", "nostubs",
718 "autoinit", "noautoinit"
720 const unsigned int optionnums = sizeof(optionnames)/sizeof(char *);
721 int optionnum;
725 for (i = 0, optionnum = 0; optionnum==0 && i<optionnums; i++)
727 if (strncmp(s, optionnames[i], strlen(optionnames[i]))==0)
729 optionnum = i + 1;
730 s += strlen(optionnames[i]);
731 while (isspace(*s)) s++;
732 if (*s == ',')
733 s++;
734 else if (*s != '\0')
735 exitfileerror(20, "Unrecognized option\n");
738 if (optionnum == 0)
739 exitfileerror(20, "Unrecognized option\n");
740 switch (optionnum)
742 case 1: /* noautolib */
743 cfg->options |= OPTION_NOAUTOLIB;
744 break;
745 case 2: /* noexpunge */
746 cfg->options |= OPTION_NOEXPUNGE;
747 break;
748 case 3: /* noresident */
749 cfg->options |= OPTION_NORESIDENT;
750 cfg->firstlvo = 1;
751 break;
752 case 5: /* peridbase */
753 cfg->options |= OPTION_DUPPERID;
754 /* Fall through */
755 case 4: /* peropenerbase */
756 if (cfg->options & OPTION_DUPBASE)
757 exitfileerror(20, "Only one option peropenerbase or peridbase allowed\n");
758 cfg->options |= OPTION_DUPBASE;
759 break;
760 case 6: /* includes */
761 if (cfg->options & OPTION_NOINCLUDES)
762 exitfileerror(20, "option includes and noincludes are incompatible\n");
763 cfg->options |= OPTION_INCLUDES;
764 break;
765 case 7: /* noincludes */
766 if (cfg->options & OPTION_INCLUDES)
767 exitfileerror(20, "option includes and noincludes are incompatible\n");
768 cfg->options |= OPTION_NOINCLUDES;
769 break;
770 case 8: /* nostubs */
771 cfg->options |= OPTION_NOSTUBS;
772 break;
773 case 9: /* autoinit */
774 if (cfg->options & OPTION_NOAUTOINIT)
775 exitfileerror(20, "option autoinit and noautoinit are incompatible\n");
776 cfg->options |= OPTION_AUTOINIT;
777 case 10: /* noautoinit */
778 if (cfg->options & OPTION_AUTOINIT)
779 exitfileerror(20, "option autoinit and noautoinit are incompatible\n");
780 cfg->options |= OPTION_NOAUTOINIT;
782 while (isspace(*s)) s++;
783 } while(*s !='\0');
785 else
787 static const char *optionnames[] =
789 "private"
791 const unsigned int optionnums = sizeof(optionnames)/sizeof(char *);
792 int optionnum;
796 for (i = 0, optionnum = 0; optionnum==0 && i<optionnums; i++)
798 if (strncmp(s, optionnames[i], strlen(optionnames[i]))==0)
800 optionnum = i + 1;
801 s += strlen(optionnames[i]);
802 while (isspace(*s)) s++;
803 if (*s == ',')
804 s++;
805 else if (*s != '\0')
806 exitfileerror(20, "Unrecognized option\n");
809 if (optionnum == 0)
810 exitfileerror(20, "Unrecognized option\n");
811 switch (optionnum)
813 case 1: /* private */
814 cl->options |= COPTION_PRIVATE;
815 break;
817 while (isspace(*s)) s++;
818 } while(*s !='\0');
820 break;
822 case 14: /* sysbase_field */
823 if (inclass)
824 exitfileerror(20, "sysbase_field not valid config option when in a class section\n");
825 cfg->sysbase_field = strdup(s);
826 break;
828 case 15: /* seglist_field */
829 if (inclass)
830 exitfileerror(20, "seglist_field not valid config option when in a class section\n");
831 cfg->seglist_field = strdup(s);
832 break;
834 case 16: /* rootbase_field */
835 if (inclass)
836 exitfileerror(20, "rootbase_field not valid config option when in a class section\n");
837 cfg->rootbase_field = strdup(s);
838 break;
840 case 17: /* classptr_field */
841 if (cl == NULL)
843 exitfileerror
846 "classptr_field specified when not a BOOPSI class\n"
849 cl->classptr_field = strdup(s);
850 break;
852 case 18: /* classptr_var */
853 if (cl == NULL)
855 exitfileerror
858 "classptr_var specified when not a BOOPSI class\n"
861 cl->classptr_var = strdup(s);
862 break;
864 case 19: /* classid */
865 if (cl == NULL)
866 exitfileerror(20, "classid specified when not a BOOPSI class\n");
867 if (cl->classid != NULL)
868 exitfileerror(20, "classid specified twice\n");
869 cl->classid = strdup(s);
870 if (strcmp(cl->classid, "NULL") == 0)
871 cl->options |= COPTION_PRIVATE;
872 break;
874 case 20: /* classdatatype */
875 if (cl == NULL)
876 exitfileerror(20, "classdatatype specified when not a BOOPSI class\n");
877 cl->classdatatype = strdup(s);
878 break;
880 case 21: /* beginio_func */
881 if (inclass)
882 exitfileerror(20, "beginio_func not valid config option when in a class section\n");
883 if (cfg->modtype != DEVICE)
884 exitfileerror(20, "beginio_func specified when not a device\n");
885 cfg->beginiofunc = strdup(s);
886 break;
888 case 22: /* abortio_func */
889 if (inclass)
890 exitfileerror(20, "abortio_func not valid config option when in a class section\n");
891 if (cfg->modtype != DEVICE)
892 exitfileerror(20, "abortio_func specified when not a device\n");
893 cfg->abortiofunc = strdup(s);
894 break;
896 case 23: /* dispatcher */
897 if (cl == NULL)
898 exitfileerror(20, "dispatcher specified when not a BOOPSI class\n");
899 cl->dispatcher = strdup(s);
900 /* function references are not needed when dispatcher is specified */
901 cfg->intcfg |= CFG_NOREADREF;
902 break;
904 case 24: /* initpri */
905 if (cl != NULL)
907 int count;
908 char dummy;
910 count = sscanf(s, "%d%c", &cl->initpri, &dummy);
911 if (count != 1 ||
912 cl->initpri < -128 || cl->initpri > 127
915 exitfileerror(20, "initpri number format error\n");
918 else
919 exitfileerror(20, "initpri only valid config option for a BOOPSI class\n");
920 break;
922 case 25: /* type */
923 if (!inclass)
924 exitfileerror(20, "type only valid config option in a class section\n");
925 if (strcmp(s,"mcc")==0)
926 cl->classtype = MCC;
927 else if (strcmp(s,"mui")==0)
928 cl->classtype = MUI;
929 else if (strcmp(s,"mcp")==0)
930 cl->classtype = MCP;
931 else if (strcmp(s, "image")==0)
932 cl->classtype = IMAGE;
933 else if (strcmp(s, "gadget")==0)
934 cl->classtype = GADGET;
935 else if (strcmp(s, "datatype")==0)
936 cl->classtype = DATATYPE;
937 else if (strcmp(s, "usbclass")==0)
938 cl->classtype = USBCLASS;
939 else if (strcmp(s, "class")==0)
940 cl->classtype = CLASS;
941 else if (strcmp(s, "hidd")==0)
942 cl->classtype = HIDD;
943 else
945 fprintf(stderr, "Unknown type \"%s\" specified\n", s);
946 exit(20);
948 break;
949 case 26: /* getidfunc */
950 cfg->getidfunc = strdup(s);
951 break;
954 else /* Line starts with ## */
956 s = line+2;
957 while (isspace(*s)) s++;
958 if (strncmp(s, "end", 3)!=0)
959 exitfileerror(20, "\"##end config\" expected\n");
961 s += 3;
962 if (!isspace(*s))
963 exitfileerror(20, "\"##end config\" expected\n");
965 while (isspace(*s)) s++;
966 if (strncmp(s, "config", 6)!=0)
967 exitfileerror(20, "\"##end config\" expected\n");
969 s += 6;
970 while (isspace(*s)) s++;
971 if (*s!='\0')
972 exitfileerror(20, "\"##end config\" expected\n");
974 atend = 1;
978 /* When not in a class section fill in default values for fields in cfg */
979 if (!inclass)
981 if (cfg->basename==NULL)
983 cfg->basename = strdup(cfg->modulename);
984 *cfg->basename = toupper(*cfg->basename);
986 if (cfg->libbase==NULL)
988 unsigned int len = strlen(cfg->basename)+5;
989 cfg->libbase = malloc(len);
990 snprintf(cfg->libbase, len, "%sBase", cfg->basename);
992 if (cfg->libbasetype == NULL && libbasetypeextern != NULL)
993 cfg->libbasetype = strdup(libbasetypeextern);
994 if (cfg->sysbase_field != NULL && cfg->libbasetype == NULL)
995 exitfileerror(20, "sysbase_field specified when no libbasetype is given\n");
996 if (cfg->seglist_field != NULL && cfg->libbasetype == NULL)
997 exitfileerror(20, "seglist_field specified when no libbasetype is given\n");
998 /* rootbase_field only allowed when duplicating base */
999 if (cfg->rootbase_field != NULL && !(cfg->options & OPTION_DUPBASE))
1000 exitfileerror(20, "rootbasefield only valid for option peropenerbase or peridbase\n");
1001 if (cfg->getidfunc != NULL && !(cfg->options & OPTION_DUPPERID))
1002 exitfileerror(20, "getidfunc only valid for option peridbase\n");
1004 /* Set default date to current date */
1005 if (cfg->datestring == NULL)
1007 char tmpbuf[256];
1008 time_t now = time(NULL);
1009 struct tm *ltime = localtime(&now);
1011 snprintf(tmpbuf, sizeof(tmpbuf), "%u.%u.%u",
1012 ltime->tm_mday, 1 + ltime->tm_mon, 1900 + ltime->tm_year);
1014 cfg->datestring = strdup(tmpbuf);
1017 if (cfg->copyright == NULL)
1018 cfg->copyright = "";
1020 if ( (cfg->beginiofunc != NULL && cfg->abortiofunc == NULL)
1021 || (cfg->beginiofunc == NULL && cfg->abortiofunc != NULL)
1023 exitfileerror(20, "please specify both beginio_func and abortio_func\n");
1025 if (libbasetypeextern==NULL)
1027 switch (cfg->modtype)
1029 case DEVICE:
1030 cfg->libbasetypeptrextern = "struct Device *";
1031 break;
1032 case RESOURCE:
1033 cfg->libbasetypeptrextern = "APTR ";
1034 break;
1035 case LIBRARY:
1036 case MUI:
1037 case MCP:
1038 case MCC:
1039 case GADGET:
1040 case DATATYPE:
1041 case USBCLASS:
1042 case HIDD:
1043 cfg->libbasetypeptrextern = "struct Library *";
1044 break;
1045 default:
1046 fprintf(stderr, "Internal error: Unsupported modtype for libbasetypeptrextern\n");
1047 exit(20);
1050 else
1052 cfg->libbasetypeptrextern = malloc(strlen(libbasetypeextern)+3);
1053 strcpy(cfg->libbasetypeptrextern, libbasetypeextern);
1054 strcat(cfg->libbasetypeptrextern, " *");
1055 free(libbasetypeextern);
1059 /* When class was given too fill in some defaults when not specified */
1060 if (cl != NULL)
1062 if (cl->classtype == UNSPECIFIED)
1063 cl->classtype = CLASS;
1065 if (cl->basename == NULL)
1067 if (!inclass)
1068 cl->basename = cfg->basename;
1069 else
1070 exitfileerror(20, "basename has to be specified in the config section inside of a class section\n");
1073 /* MUI classes are always private */
1074 if (cl->classtype == MUI || cl->classtype == MCC || cl->classtype == MCP)
1075 cl->options |= COPTION_PRIVATE;
1077 if (cl->classid == NULL
1078 && (cl->classtype != MUI && cl->classtype != MCC && cl->classtype != MCP)
1081 if (cl->classtype == HIDD)
1083 cl->options &= !COPTION_PRIVATE;
1085 else if (cl->options & COPTION_PRIVATE)
1087 cl->classid = "NULL";
1089 else
1091 char s[256] = "";
1093 if (cl->classtype == GADGET || cl->classtype == IMAGE || cl->classtype == CLASS || cl->classtype == USBCLASS)
1095 sprintf(s, "\"%sclass\"", inclass ? cl->basename : cfg->modulename);
1097 else if (cl->classtype == DATATYPE)
1099 sprintf(s, "\"%s.datatype\"", inclass ? cl->basename : cfg->modulename);
1101 cl->classid = strdup(s);
1105 /* Only specify superclass or superclass_field */
1106 if (cl->superclass != NULL && cl->superclass_field != NULL)
1107 exitfileerror(20, "Only specify one of superclass or superclass_field in config section\n");
1109 /* Give default value to superclass if it is not specified */
1110 if (cl->superclass == NULL && cl->superclass == NULL)
1112 switch (cl->classtype)
1114 case MUI:
1115 case MCC:
1116 cl->superclass = "MUIC_Area";
1117 break;
1118 case MCP:
1119 cl->superclass = "MUIC_Mccprefs";
1120 break;
1121 case IMAGE:
1122 cl->superclass = "IMAGECLASS";
1123 break;
1124 case GADGET:
1125 cl->superclass = "GADGETCLASS";
1126 break;
1127 case DATATYPE:
1128 cl->superclass = "DATATYPESCLASS";
1129 break;
1130 case CLASS:
1131 cl->superclass = "ROOTCLASS";
1132 break;
1133 case HIDD:
1134 cl->superclass = "CLID_Root";
1135 break;
1136 default:
1137 exitfileerror(20, "Internal error: unhandled classtype in readsectionconfig\n");
1138 break;
1144 static void readsectioncdef(struct config *cfg)
1146 int atend = 0;
1147 char *line, *s;
1149 while (!atend)
1151 line = readline();
1152 if (line==NULL)
1153 exitfileerror(20, "unexptected end of file in section cdef\n");
1155 if (strncmp(line, "##", 2)!=0)
1157 slist_append(&cfg->cdeflines, line);
1159 else
1161 s = line+2;
1162 while (isspace(*s)) s++;
1163 if (strncmp(s, "end", 3)!=0)
1164 exitfileerror(20, "\"##end cdef\" expected\n");
1166 s += 3;
1167 while (isspace(*s)) s++;
1168 if (strncmp(s, "cdef", 4)!=0)
1169 exitfileerror(20, "\"##end cdef\" expected\n");
1171 s += 5;
1172 while (isspace(*s)) s++;
1173 if (*s!='\0')
1174 exitfileerror(20, "unexpected character at position %d\n");
1176 atend = 1;
1181 static void readsectioncdefprivate(struct config *cfg)
1183 int atend = 0;
1184 char *line, *s;
1186 while (!atend)
1188 line = readline();
1189 if (line==NULL)
1190 exitfileerror(20, "unexptected end of file in section cdef\n");
1192 if (strncmp(line, "##", 2)!=0)
1194 slist_append(&cfg->cdefprivatelines, line);
1196 else
1198 s = line+2;
1199 while (isspace(*s)) s++;
1200 if (strncmp(s, "end", 3)!=0)
1201 exitfileerror(20, "\"##end cdefprivate\" expected\n");
1203 s += 3;
1204 while (isspace(*s)) s++;
1205 if (strncmp(s, "cdefprivate", 11)!=0)
1206 exitfileerror(20, "\"##end cdefprivate\" expected\n");
1208 s += 11;
1209 while (isspace(*s)) s++;
1210 if (*s!='\0')
1211 exitfileerror(20, "unexpected character at position %d\n");
1213 atend = 1;
1218 static void readsectionstartup(struct config *cfg)
1220 int atend = 0;
1221 char *line, *s;
1223 while (!atend)
1225 line = readline();
1226 if (line==NULL)
1227 exitfileerror(20, "unexptected end of file in section startup\n");
1229 if (strncmp(line, "##", 2)!=0)
1231 slist_append(&cfg->startuplines, line);
1233 else
1235 s = line+2;
1236 while (isspace(*s)) s++;
1237 if (strncmp(s, "end", 3)!=0)
1238 exitfileerror(20, "\"##end startup\" expected\n");
1240 s += 3;
1241 while (isspace(*s)) s++;
1242 if (strncmp(s, "startup", 7)!=0)
1243 exitfileerror(20, "\"##end startup\" expected\n");
1245 s += 7;
1246 while (isspace(*s)) s++;
1247 if (*s!='\0')
1248 exitfileerror(20, "unexpected character at position %d\n");
1250 atend = 1;
1255 static void readsectionfunctionlist(struct config *cfg)
1257 int atend = 0, i;
1258 char *line, *s, *s2;
1259 unsigned int lvo = cfg->firstlvo;
1260 struct functionhead **funclistptr = &cfg->funclist;
1262 if (cfg->basename==NULL)
1263 exitfileerror(20, "section functionlist has to come after section config\n");
1265 while (!atend)
1267 line = readline();
1268 if (line==NULL)
1269 exitfileerror(20, "unexptected EOF in functionlist section\n");
1270 if (strlen(line)==0)
1272 if (*funclistptr != NULL)
1273 funclistptr = &((*funclistptr)->next);
1274 lvo++;
1276 else if (isspace(*line))
1278 s = line;
1279 while (isspace(*s)) s++;
1280 if (*s=='\0')
1282 if (*funclistptr != NULL)
1283 funclistptr = &((*funclistptr)->next);
1284 lvo++;
1286 else
1287 exitfileerror(20, "no space allowed before functionname\n");
1289 else if (strncmp(line, "##", 2)==0)
1291 s = line+2;
1292 while (isspace(*s)) s++;
1293 if (strncmp(s, "end", 3)!=0)
1294 exitfileerror(20, "\"##end functionlist\" expected\n");
1296 s += 3;
1297 while (isspace(*s)) s++;
1298 if (strncmp(s, "functionlist", 12)!=0)
1299 exitfileerror(20, "\"##end functionlist\" expected\n");
1301 s += 12;
1302 while (isspace(*s)) s++;
1303 if (*s!='\0')
1304 exitfileerror(20, "unexpected character on position %d\n", s-line);
1306 atend = 1;
1308 else if (*line=='.')
1310 s = line+1;
1311 if (strncmp(s, "skip", 4)==0)
1313 int n;
1315 s += 4;
1316 if (!isspace(*s))
1317 exitfileerror(20, "syntax is '.skip n'\n");
1319 n=strtol(s, &s2, 10);
1320 if (s2==NULL)
1321 exitfileerror(20, "positive number expected\n");
1323 while (isspace(*s2)) s2++;
1324 if (*s2!='\0')
1325 exitfileerror(20, "syntax is '.skip n'\n");
1326 if (*funclistptr != NULL)
1327 funclistptr = &((*funclistptr)->next);
1328 lvo += n;
1330 else if (strncmp(s, "alias", 5)==0)
1332 s += 5;
1334 if (!isspace(*s))
1335 exitfileerror(20, "syntax is '.alias name'\n");
1337 while (isspace(*s)) s++;
1338 if (*s == '\0' || !(isalpha(*s) || *s == '_'))
1339 exitfileerror(20, "syntax is '.alias name'\n");
1341 s2 = s;
1342 s++;
1343 while (isalnum(*s) || *s == '_') s++;
1345 if (isspace(*s))
1347 *s = '\0';
1348 do {
1349 s++;
1350 } while (isspace(*s));
1353 if (*s != '\0')
1354 exitfileerror(20, "syntax is '.alias name'\n");
1356 if (*funclistptr == NULL)
1357 exitfileerror(20, ".alias has to come after a function declaration\n");
1359 slist_append(&(*funclistptr)->aliases, s2);
1360 cfg->intcfg |= CFG_GENASTUBS;
1362 else if (strncmp(s, "cfunction", 9)==0)
1364 if (*funclistptr == NULL)
1365 exitfileerror(20, ".cfunction has to come after a function declaration\n");
1367 (*funclistptr)->libcall = REGISTER;
1369 else if (strncmp(s, "private", 7)==0)
1371 if (*funclistptr == NULL)
1372 exitfileerror(20, ".private has to come after a function declaration\n");
1374 (*funclistptr)->priv = 1;
1376 else if (strncmp(s, "novararg", 8)==0)
1378 if (*funclistptr == NULL)
1379 exitfileerror(20, ".novararg has to come after a function declaration\n");
1381 (*funclistptr)->novararg = 1;
1383 else
1384 exitfileerror(20, "Syntax error");
1386 else if (*line!='#') /* Ignore line that is a comment, e.g. that starts with a # */
1388 /* The line is a function prototype. It can have two syntax
1389 * type funcname(argproto1, argproto2, ...)
1390 * type funcname(argproto1, argproto2, ...) (reg1, reg2, ...)
1391 * The former is for C type function argument passing, the latter for
1392 * register argument passing.
1394 char c, *args[64], *regs[64], *funcname;
1395 int len, argcount = 0, regcount = 0, brcount = 0;
1397 /* Parse 'type functionname' at the beginning of the line */
1398 s = strchr(line, '(');
1399 if (s == NULL)
1400 exitfileerror(20, "( expected at position %d\n", strlen(line) + 1);
1402 s2 = s;
1403 while (isspace(*(s2-1)))
1404 s2--;
1405 *s2 = '\0';
1407 while (s2 > line && !isspace(*(s2-1)) && !(*(s2-1) == '*'))
1408 s2--;
1410 if (s2 == line)
1411 exitfileerror(20, "No type specifier before function name\n");
1413 if (*funclistptr != NULL)
1414 funclistptr = &((*funclistptr)->next);
1415 *funclistptr = newfunctionhead(s2, STACK);
1417 while (isspace(*(s2-1)))
1418 s2--;
1419 *s2 = '\0';
1420 (*funclistptr)->type = strdup(line);
1421 (*funclistptr)->lvo = lvo;
1422 lvo++;
1424 /* Parse function prototype */
1425 s++;
1426 while (isspace(*s))
1427 s++;
1428 c = *s;
1430 while (c != ')')
1432 while (isspace(*s))
1433 s++;
1435 args[argcount] = s;
1436 argcount++;
1438 while
1440 *s != '\0'
1441 && !(brcount == 0 && (*s == ',' || *s == ')'))
1444 if (*s == '(')
1445 brcount++;
1446 if (*s == ')')
1448 if (brcount > 0)
1449 brcount--;
1450 else
1451 exitfileerror(20, "Unexected ')' at position %d\n", s-line+1);
1453 s++;
1456 c = *s;
1457 if (c == '\0')
1458 exitfileerror(20, "'(' without ')'");
1460 s2 = s;
1461 while (isspace(*(s2-1)))
1462 s2--;
1463 *s2 = '\0';
1465 if (!(s2 > args[argcount - 1]))
1466 exitfileerror(20, "Syntax error in function prototype\n");
1468 s++;
1471 s++;
1472 while (*s != '\0' && isspace(*s))
1473 s++;
1475 if (*s == '(')
1477 /* Parse registers specifications if available otherwise this prototype for C type argument passing */
1479 /* There may be no register specified with () so be sure then c is == ')' */
1480 s++;
1481 while(isspace(*s))
1482 s++;
1484 c = *s;
1486 while (c != ')')
1488 while (isspace(*s))
1489 s++;
1491 regs[regcount] = s;
1492 regcount++;
1494 if (memchr("AD",s[0],2)!=NULL && memchr("01234567",s[1],8)!=NULL)
1496 s += 2;
1497 c = *s;
1498 if (c == '/')
1500 if (regcount > 1)
1502 if (strchr(regs[0], '/') == NULL)
1503 exitfileerror(20, "Either all arguments has to in two registers or none\n");
1506 s++;
1507 if (s[0] == s[-3] && s[1] == s[-2] + 1)
1509 s += 2;
1510 c = *s;
1512 else
1513 exitfileerror(20,
1514 "wrong register specification \"%s\" for argument %u\n",
1515 regs[regcount-1], regcount
1518 if (regcount > 2)
1519 exitfileerror(20, "maximum two arguments passed in two registers allowed\n");
1521 *s = '\0';
1523 else
1524 exitfileerror(20,
1525 "wrong register \"%s\" for argument %u\n",
1526 regs[regcount-1], regcount
1529 while (isspace(c))
1531 s++;
1532 c = *s;
1534 if (c == '\0')
1535 exitfileerror(20, "'(' without ')'\n");
1536 if (c != ',' && c != ')')
1537 exitfileerror(20, "',' or ')' expected at position %d\n", s-line+1);
1539 s++;
1542 s++;
1543 while (isspace(*s)) s++;
1544 if (*s!='\0')
1545 exitfileerror(20, "wrong char '%c' at position %d\n", *s, (int)(s-line) + 1);
1547 if (argcount != regcount)
1548 exitfileerror(20, "Number of arguments (%d) and registers (%d) mismatch\n",
1549 argcount, regcount
1552 (*funclistptr)->libcall = REGISTERMACRO;
1553 for (i = 0; i < argcount; i++)
1554 funcaddarg(*funclistptr, args[i], regs[i]);
1556 else if (*s == '\0')
1557 { /* No registers specified */
1558 for (i = 0; i < argcount; i++)
1559 funcaddarg(*funclistptr, args[i], NULL);
1560 cfg->intcfg |= CFG_GENASTUBS;
1562 else
1563 exitfileerror(20, "wrong char '%c' at position %d\n", *s, (int)(s-line) + 1);
1568 static void readsectionmethodlist(struct classinfo *cl)
1570 int atend = 0, i;
1571 char *line, *s, *s2;
1572 struct functionhead **methlistptr = &cl->methlist;
1573 struct stringlist *interface = NULL;
1575 if (cl->basename==NULL)
1576 exitfileerror(20, "section methodlist has to come after section config\n");
1578 while (!atend)
1580 line = readline();
1581 if (line==NULL)
1582 exitfileerror(20, "unexptected EOF in methodlist section\n");
1584 /* Ignore empty lines or lines that qre a comment, e.g. that starts with a # */
1585 if (strlen(line)==0 || (line[0] == '#' && line[1] != '#'))
1586 continue;
1588 if (isspace(*line))
1589 exitfileerror(20, "No space allowed at start of the line\n");
1591 if (strncmp(line, "##", 2)==0) /* Is this the end ? */
1593 s = line+2;
1594 while (isspace(*s)) s++;
1595 if (strncmp(s, "end", 3)!=0)
1596 exitfileerror(20, "\"##end methodlist\" expected\n");
1598 s += 3;
1599 while (isspace(*s)) s++;
1600 if (strncmp(s, "methodlist", 10)!=0)
1601 exitfileerror(20, "\"##end methodlist\" expected\n");
1603 s += 10;
1604 while (isspace(*s)) s++;
1605 if (*s!='\0')
1606 exitfileerror(20, "unexpected character on position %d\n", s-line);
1608 atend = 1;
1610 continue;
1613 if (*line=='.')
1615 s = line+1;
1616 if (strncmp(s, "alias", 5)==0)
1618 s += 5;
1620 if (!isspace(*s))
1621 exitfileerror(20, "syntax is '.alias name'\n");
1623 while (isspace(*s)) s++;
1624 if (*s == '\0' || !(isalpha(*s) || *s == '_'))
1625 exitfileerror(20, "syntax is '.alias name'\n");
1627 s2 = s;
1628 s++;
1629 while (isalnum(*s) || *s == '_') s++;
1631 if (isspace(*s))
1633 *s = '\0';
1634 do {
1635 s++;
1636 } while (isspace(*s));
1639 if (*s != '\0')
1640 exitfileerror(20, "syntax is '.alias name'\n");
1642 if (*methlistptr == NULL)
1643 exitfileerror(20, ".alias has to come after a function declaration\n");
1645 slist_append(&(*methlistptr)->aliases, s2);
1647 else if (strncmp(s, "function", 8) == 0)
1649 s += 8;
1651 if (!isspace(*s))
1652 exitfileerror(20, "Syntax error\n");
1654 while (isspace(*s)) s++;
1655 if (*s == '\0' || !(isalpha(*s) || *s == '_'))
1656 exitfileerror(20, "syntax is '.function name'\n");
1658 s2 = s;
1659 s++;
1660 while (isalnum(*s) || *s == '_') s++;
1662 if (isspace(*s))
1664 *s = '\0';
1665 do {
1666 s++;
1667 } while (isspace(*s));
1670 if (*s != '\0')
1671 exitfileerror(20, "syntax is '.function name'\n");
1673 if (*methlistptr == NULL)
1674 exitfileerror(20, ".function has to come after a function declaration\n");
1676 free((*methlistptr)->name);
1677 (*methlistptr)->name = strdup(s2);
1679 else if (strncmp(s, "interface", 9) == 0)
1681 if (cl->classtype != HIDD)
1682 exitfileerror(20, "interface only valid for a HIDD\n");
1684 s += 9;
1686 if (!isspace(*s))
1687 exitfileerror(20, "Syntax error\n");
1689 while (isspace(*s)) s++;
1690 if (*s == '\0' || !isalpha(*s))
1691 exitfileerror(20, "syntax is '.interface name'\n");
1693 s2 = s;
1694 s++;
1695 while (isalnum(*s) || *s == '_') s++;
1697 if (isspace(*s))
1699 *s = '\0';
1700 do {
1701 s++;
1702 } while (isspace(*s));
1705 if (*s != '\0')
1706 exitfileerror(20, "syntax is '.interface name'\n");
1708 interface = slist_append(&cl->interfaces, s2);
1710 else
1711 exitfileerror(20, "Syntax error");
1713 else if (isalpha(*line))
1715 char stmp[256];
1717 for (s = line + 1; isalnum(*s) || *s == '_'; s++)
1720 if (cl->classtype == HIDD && interface == NULL)
1721 exitfileerror(20, "For a HIDD the first method has to come after an .interface line\n");
1723 if (*s != '\0')
1724 exitfileerror(20, "Only letters, digits and an underscore allowed in a methodname\n");
1726 if (*methlistptr != NULL)
1727 methlistptr = &((*methlistptr)->next);
1728 if (cl->classtype != HIDD)
1730 if (snprintf(stmp, 256, "%s__%s", cl->basename, line) >= 256)
1731 exitfileerror(20, "Method name too large\n");
1733 *methlistptr = newfunctionhead(stmp, STACK);
1734 (*methlistptr)->type = "IPTR";
1735 funcaddarg(*methlistptr, "Class *cl", NULL);
1736 funcaddarg(*methlistptr, "Object *o", NULL);
1737 funcaddarg(*methlistptr, "Msg msg", NULL);
1739 else
1741 if (snprintf(stmp, 256, "%s__%s__%s", cl->basename, interface->s, line) >= 256)
1742 exitfileerror(20, "Method name too large\n");
1744 *methlistptr = newfunctionhead(stmp, STACK);
1745 (*methlistptr)->type = "IPTR";
1746 funcaddarg(*methlistptr, "OOP_Class *cl", NULL);
1747 funcaddarg(*methlistptr, "OOP_Object *o", NULL);
1748 funcaddarg(*methlistptr, "OOP_Msg msg", NULL);
1749 (*methlistptr)->interface = interface;
1750 if (snprintf(stmp, 256, "mo%s_%s", interface->s, line) >= 256)
1751 exitfileerror(20, "Method name too large\n");
1752 (*methlistptr)->method = strdup(stmp);
1754 slist_append(&(*methlistptr)->aliases, line);
1756 else
1757 exitfileerror(20, "Methodname has to begin with a letter\n");
1761 static void
1762 readsectionclass(struct config *cfg)
1764 char *s;
1765 struct classinfo *cl;
1767 cl = newclass(cfg);
1768 s = readsections(cfg, cl, 1);
1769 if (s == NULL)
1770 exitfileerror(20, "Unexpected end of file\n");
1772 if (strncmp(s, "##", 2) != 0)
1773 exitfileerror(20, "'##end class' expected\n");
1774 s += 2;
1776 while (isspace(*s)) s++;
1778 if (strncmp(s, "end", 3) != 0)
1779 exitfileerror(20, "'##end class' expected\n");
1780 s += 3;
1782 if (!isspace(*s))
1783 exitfileerror(20, "'##end class' expected\n");
1784 while (isspace(*s)) s++;
1786 if (strncmp(s, "class", 5) != 0)
1787 exitfileerror(20, "'##end class' expected\n");
1788 s += 5;
1790 while (isspace(*s)) s++;
1791 if (*s != '\0')
1792 exitfileerror(20, "'##end class' expected\n");
1795 static struct classinfo *newclass(struct config *cfg)
1797 struct classinfo *cl, *classlistit;
1799 cl = malloc(sizeof(struct classinfo));
1800 if (cl == NULL)
1802 fprintf(stderr, "Out of memory\n");
1803 exit(20);
1805 memset(cl, 0, sizeof(struct classinfo));
1807 /* By default the classes are initialized with a priority of 1 so they
1808 * are initialized before any user added initialization with priority 1
1810 cl->initpri = 1;
1812 if (cfg->classlist == NULL)
1813 cfg->classlist = cl;
1814 else
1818 classlistit = cfg->classlist;
1819 classlistit->next != NULL;
1820 classlistit = classlistit->next
1823 classlistit->next = cl;
1826 return cl;