- Set a default PCM volume so that something can be heard when driver is
[AROS.git] / tools / genmodule / config.c
blobfbc9bea779dae26875136f8187e649063e186a25
1 /*
2 Copyright © 1995-2011, 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 #define __USE_XOPEN
13 #include <time.h>
14 #include <unistd.h>
16 #include "functionhead.h"
17 #include "config.h"
19 const static char bannertemplate[] =
20 "/*\n"
21 " *** Automatically generated from '%s'. Edits will be lost. ***\n"
22 " Copyright © 1995-2011, The AROS Development Team. All rights reserved.\n"
23 "*/\n";
25 char*
26 getBanner(struct config* config)
28 int bannerlength = strlen(config->conffile) + strlen(bannertemplate) -1;
29 char * banner = malloc(bannerlength);
31 snprintf (banner, bannerlength, bannertemplate, config->conffile);
33 return(banner);
36 void
37 freeBanner(char *banner)
39 free((void *)banner);
42 const static char usage[] =
43 "\n"
44 "Usage: genmodule [-c conffile] [-s suffix] [-d gendir] [-n]\n"
45 " {writefiles|writemakefile|writeincludes|writelibdefs|writefunclist} modname modtype\n"
48 static void readconfig(struct config *);
49 static struct classinfo *newclass(struct config *);
51 /* the method prefices for the supported classes */
52 static const char *muimprefix[] =
54 "__OM_",
55 "__MUIM_",
56 NULL
58 static const char *gadgetmprefix[] =
60 "__OM_",
61 "__GM_",
62 "__AROSM_",
63 NULL
65 static const char *dtmprefix[] =
67 "__OM_",
68 "__GM_",
69 "__DTM_",
70 "__PDTM_",
71 NULL
74 /* Create a config struct. Initialize with the values from the programs command
75 * line arguments and the contents of the modules .conf file
77 struct config *initconfig(int argc, char **argv)
79 struct config *cfg;
80 char *s, **argvit = argv + 1;
81 int hassuffix = 0, c;
83 cfg = malloc(sizeof(struct config));
84 if (cfg == NULL)
86 fprintf(stderr, "Out of memory\n");
87 exit(20);
90 memset(cfg, 0, sizeof(struct config));
92 while ((c = getopt(argc, argv, ":c:s:d:")) != -1)
94 if (c == ':')
96 fprintf(stderr, "Option -%c needs an argument\n",optopt);
97 exit(20);
100 switch (c)
102 case 'c':
103 cfg->conffile = optarg;
104 break;
105 case 's':
106 cfg->suffix = optarg;
107 hassuffix = 1;
108 break;
109 case 'd':
110 /* Remove / at end if present */
111 if ((optarg)[strlen(*argvit)-1]=='/') (optarg)[strlen(optarg)-1]='\0';
112 cfg->gendir = optarg;
113 break;
114 default:
115 fprintf(stderr, "Internal error: Unhandled option\n");
116 exit(20);
120 if (optind + 3 != argc)
122 fprintf(stderr, "Wrong number of arguments.\n%s", usage);
123 exit(20);
126 if (strcmp(argv[optind], "writefiles") == 0)
128 cfg->command = FILES;
130 else if (strcmp(argv[optind], "writemakefile") == 0)
132 cfg->command = MAKEFILE;
134 else if (strcmp(argv[optind], "writeincludes") == 0)
136 cfg->command = INCLUDES;
138 else if (strcmp(argv[optind], "writelibdefs") == 0)
140 cfg->command = LIBDEFS;
142 else if (strcmp(argv[optind], "writefunclist") == 0)
144 cfg->command = WRITEFUNCLIST;
146 else
148 fprintf(stderr, "Unrecognized argument \"%s\"\n%s", argv[optind], usage);
149 exit(20);
152 cfg->modulename = argv[optind+1];
153 cfg->modulenameupper = strdup(cfg->modulename);
154 for (s=cfg->modulenameupper; *s!='\0'; *s = toupper(*s), s++)
157 if (strcmp(argv[optind+2],"library")==0)
159 cfg->modtype = LIBRARY;
160 cfg->moddir = "Libs";
162 else if (strcmp(argv[optind+2],"mcc")==0)
164 cfg->modtype = MCC;
165 cfg->moddir = "Classes/Zune";
167 else if (strcmp(argv[optind+2],"mui")==0)
169 cfg->modtype = MUI;
170 cfg->moddir = "Classes/Zune";
172 else if (strcmp(argv[optind+2],"mcp")==0)
174 cfg->modtype = MCP;
175 cfg->moddir = "Classes/Zune";
177 else if (strcmp(argv[optind+2], "device")==0)
179 cfg->modtype = DEVICE;
180 cfg->moddir = "Devs";
182 else if (strcmp(argv[optind+2], "resource")==0)
184 cfg->modtype = RESOURCE;
185 cfg->moddir = "Devs";
187 else if (strcmp(argv[optind+2], "gadget")==0)
189 cfg->modtype = GADGET;
190 cfg->moddir = "Classes/Gadgets";
192 else if (strcmp(argv[optind+2], "datatype")==0)
194 cfg->modtype = DATATYPE;
195 cfg->moddir = "Classes/Datatypes";
197 else if (strcmp(argv[optind+2], "usbclass")==0)
199 cfg->modtype = USBCLASS;
200 cfg->moddir = "Classes/USB";
201 if(!hassuffix)
203 cfg->suffix = "class";
204 hassuffix = 1;
207 else if (strcmp(argv[optind+2], "hidd")==0)
209 cfg->modtype = HIDD;
210 cfg->moddir = "Devs/Drivers";
212 else
214 fprintf(stderr, "Unknown modtype \"%s\" specified for second argument\n", argv[2]);
215 exit(20);
218 if (!hassuffix)
219 cfg->suffix = argv[optind+2];
221 /* Fill fields with default value if not specified on the command line */
223 char tmpbuf[256];
225 if (cfg->conffile == NULL)
227 snprintf(tmpbuf, sizeof(tmpbuf), "%s.conf", cfg->modulename);
228 cfg->conffile = strdup(tmpbuf);
231 if (cfg->gendir == NULL)
232 cfg->gendir = ".";
235 readconfig(cfg);
237 /* For a device add the functions given in beginiofunc and abortiofunc to the functionlist
238 * if they are provided
240 if (cfg->beginiofunc != NULL)
242 struct functionhead *funchead;
244 cfg->intcfg |= CFG_NOREADFUNCS;
246 /* Add beginio_func to the list of functions */
247 funchead = newfunctionhead(cfg->beginiofunc, REGISTERMACRO);
248 funchead->type = strdup("void");
249 funchead->lvo = 5;
250 funcaddarg(funchead, "struct IORequest *ioreq", "A1");
252 funchead->next = cfg->funclist;
253 cfg->funclist = funchead;
255 /* Add abortio_func to the list of functions */
256 funchead = newfunctionhead(cfg->abortiofunc, REGISTERMACRO);
257 funchead->type = strdup("LONG");
258 funchead->lvo = 6;
259 funcaddarg(funchead, "struct IORequest *ioreq", "A1");
261 funchead->next = cfg->funclist->next;
262 cfg->funclist->next = funchead;
264 else if (cfg->modtype == DEVICE && cfg->intcfg & CFG_NOREADFUNCS)
266 fprintf
268 stderr,
269 "beginio_func and abortio_func missing for a device with a non empty function list\n"
271 exit(20);
274 return cfg;
277 /* Functions to read configuration from the configuration file */
279 #include "fileread.h"
281 static char *readsections(struct config *, struct classinfo *, int);
282 static void readsectionconfig(struct config *, struct classinfo *, int);
283 static void readsectioncdef(struct config *);
284 static void readsectioncdefprivate(struct config *);
285 static void readsectionstartup(struct config *);
286 static void readsectionfunctionlist(struct config *);
287 static void readsectionmethodlist(struct classinfo *);
288 static void readsectionclass(struct config *);
290 static void readconfig(struct config *cfg)
292 struct classinfo *mainclass = NULL;
294 /* Create a classinfo structure if this module is a class */
295 switch (cfg->modtype)
297 case LIBRARY:
298 case DEVICE:
299 case RESOURCE:
300 case USBCLASS:
301 break;
303 case MCC:
304 case MUI:
305 case MCP:
306 case GADGET:
307 case DATATYPE:
308 case HIDD:
309 mainclass = newclass(cfg);
310 mainclass->classtype = cfg->modtype;
311 break;
313 default:
314 fprintf(stderr, "Internal error: unsupported modtype for classinfo creation\n");
315 exit(20);
318 switch (cfg->modtype)
320 case LIBRARY:
321 case USBCLASS:
322 cfg->firstlvo = 5;
323 break;
324 case DEVICE:
325 cfg->firstlvo = 7;
326 break;
327 case MCC:
328 case MUI:
329 case MCP:
330 cfg->firstlvo = 6;
331 mainclass->boopsimprefix = muimprefix;
332 break;
333 case RESOURCE:
334 cfg->firstlvo = 1;
335 break;
336 case GADGET:
337 cfg->firstlvo = 5;
338 mainclass->boopsimprefix = gadgetmprefix;
339 break;
340 case DATATYPE:
341 cfg->firstlvo = 6;
342 mainclass->boopsimprefix = dtmprefix;
343 break;
344 case HIDD:
345 cfg->firstlvo = 5;
346 /* FIXME: need boopsimprefix ? */
347 break;
348 default:
349 fprintf(stderr, "Internal error: unsupported modtype for firstlvo\n");
350 exit(20);
353 if (!fileopen(cfg->conffile))
355 fprintf(stderr, "In readconfig: Could not open %s\n", cfg->conffile);
356 exit(20);
359 /* Read all sections and see that we are at the end of the file */
360 if (readsections(cfg, mainclass, 0) != NULL)
361 exitfileerror(20, "Syntax error");
363 fileclose();
366 /* readsections will scan through all the sections in the config file.
367 * arguments:
368 * struct config *cfg: The module config data which may be updated by
369 * the information in the sections
370 * struct classinfo *cl: The classdata to be filled with data from the sections.
371 * This may be NULL if this is the main part of the configuration file and the
372 * type of the module is not a class
373 * int inclass: Boolean to indicate if we are in a class part. If not we are in the main
374 * part of the config file.
376 static char *readsections(struct config *cfg, struct classinfo *cl, int inclass)
378 char *line, *s, *s2;
379 int hasconfig = 0;
381 while ((line=readline())!=NULL)
383 if (strncmp(line, "##", 2)==0)
385 static char *parts[] =
387 "config", "cdefprivate", "cdef", "startup", "functionlist", "methodlist", "class"
389 const unsigned int nums = sizeof(parts)/sizeof(char *);
390 unsigned int partnum;
391 int i, atend = 0;
393 s = line+2;
394 while (isspace(*s)) s++;
396 if (strncmp(s, "begin", 5)!=0)
397 return line;
399 s += 5;
400 if (!isspace(*s))
401 exitfileerror(20, "space after begin expected\n");
402 while (isspace(*s)) s++;
404 for (i = 0, partnum = 0; partnum==0 && i<nums; i++)
406 if (strncmp(s, parts[i], strlen(parts[i]))==0)
408 partnum = i+1;
409 s += strlen(parts[i]);
410 while (isspace(*s)) s++;
411 if (*s!='\0')
412 exitfileerror(20, "unexpected character on position %d\n", s-line);
415 if (partnum==0)
416 exitfileerror(20, "unknown start of section\n");
417 switch (partnum)
419 case 1: /* config */
420 readsectionconfig(cfg, cl, inclass);
421 hasconfig = 1;
422 break;
424 case 2: /* cdefprivate */
425 if (inclass)
426 exitfileerror(20, "cdefprivate section not allowed in class section\n");
427 readsectioncdefprivate(cfg);
428 break;
430 case 3: /* cdef */
431 if (inclass)
432 exitfileerror(20, "cdef section not allowed in class section\n");
433 readsectioncdef(cfg);
434 break;
436 case 4: /* startup */
437 if (inclass)
438 exitfileerror(20, "startup section not allowed in class section\n");
439 readsectionstartup(cfg);
440 break;
442 case 5: /* functionlist */
443 if (inclass)
444 exitfileerror(20, "functionlist section not allow in class section\n");
445 readsectionfunctionlist(cfg);
446 cfg->intcfg |= CFG_NOREADFUNCS;
447 break;
449 case 6: /* methodlist */
450 if (cl == NULL)
451 exitfileerror(20, "methodlist section when not in a class\n");
452 readsectionmethodlist(cl);
453 cfg->intcfg |= CFG_NOREADFUNCS;
454 break;
456 case 7: /* class */
457 if (inclass)
458 exitfileerror(20, "class section may not be nested\n");
459 readsectionclass(cfg);
460 break;
463 else if (strlen(line)!=0)
464 filewarning("warning line outside section ignored\n");
467 if(!inclass)
469 if (!hasconfig)
470 exitfileerror(20, "No config section in conffile\n");
472 /* If no indication was given for generating includes or not
473 decide on module type and if there are functions
475 if(!((cfg->options & OPTION_INCLUDES) || (cfg->options & OPTION_NOINCLUDES)))
477 switch (cfg->modtype)
479 case LIBRARY:
480 case RESOURCE:
481 case USBCLASS:
482 cfg->options |= OPTION_INCLUDES;
483 break;
485 case DEVICE:
486 cfg->options |= (
487 (cfg->funclist != NULL)
488 || (cfg->cdeflines != NULL)
489 || strcmp(cfg->libbasetypeptrextern, "struct Device *") != 0
490 ) ? OPTION_INCLUDES : OPTION_NOINCLUDES;
491 break;
493 case GADGET:
494 case DATATYPE:
495 case MCC:
496 case MUI:
497 case MCP:
498 case HIDD:
499 cfg->options |= (
500 (cfg->funclist != NULL)
501 || (cfg->cdeflines != NULL)
502 ) ? OPTION_INCLUDES : OPTION_NOINCLUDES;
503 break;
505 default:
506 fprintf(stderr, "Internal error writemakefile: unhandled modtype for includes\n");
507 exit(20);
508 break;
512 /* If no indication was given for not generating stubs only generate them if
513 * the module has functions
515 if(!((cfg->options & OPTION_STUBS) || (cfg->options & OPTION_NOSTUBS)))
517 cfg->options |= (cfg->funclist != NULL) ?
518 OPTION_STUBS : OPTION_NOSTUBS;
521 /* If no indication was given for generating autoinit code or not
522 decide on module type
524 if(!((cfg->options & OPTION_AUTOINIT) || (cfg->options & OPTION_NOAUTOINIT)))
526 switch (cfg->modtype)
528 case LIBRARY:
529 case USBCLASS:
530 cfg->options |= OPTION_AUTOINIT;
531 break;
533 case RESOURCE:
534 case GADGET:
535 case DEVICE:
536 case DATATYPE:
537 case MCC:
538 case MUI:
539 case MCP:
540 case HIDD:
541 cfg->options |= OPTION_NOAUTOINIT;
542 break;
544 default:
545 fprintf(stderr, "Internal error writemakefile: unhandled modtype for autoinit\n");
546 exit(20);
547 break;
551 if (cfg->modtype == RESOURCE)
552 /* Enforce noopenclose for resources */
553 cfg->options |= OPTION_NOOPENCLOSE;
554 else
555 /* Enforce using RTF_AUTOINIT for everything except resources */
556 if (!(cfg->options & OPTION_SELFINIT))
557 cfg->options |= OPTION_RESAUTOINIT;
560 return NULL;
563 static void readsectionconfig(struct config *cfg, struct classinfo *cl, int inclass)
565 int atend = 0, i;
566 char *line, *s, *s2, *libbasetypeextern = NULL;
567 struct tm date;
569 while (!atend)
571 line = readline();
572 if (line==NULL)
573 exitfileerror(20, "unexpected end of file in section config\n");
575 if (strncmp(line, "##", 2)!=0)
577 const char *names[] =
579 "basename", "libbase", "libbasetype", "libbasetypeextern",
580 "version", "date", "copyright", "libcall", "forcebase", "superclass",
581 "superclass_field", "residentpri", "options", "sysbase_field",
582 "seglist_field", "rootbase_field", "classptr_field", "classptr_var",
583 "classid", "classdatatype", "beginio_func", "abortio_func", "dispatcher",
584 "initpri", "type", "getidfunc", "addromtag"
586 const unsigned int namenums = sizeof(names)/sizeof(char *);
587 unsigned int namenum;
589 for (i = 0, namenum = 0; namenum==0 && i<namenums; i++)
593 strncmp(line, names[i], strlen(names[i]))==0
594 && isspace(*(line+strlen(names[i])))
596 namenum = i+1;
598 if (namenum==0)
599 exitfileerror(20, "unrecognized configuration option\n");
601 s = line + strlen(names[namenum-1]);
602 if (!isspace(*s))
603 exitfileerror(20, "space character expected after \"%s\"\n", names[namenum-1]);
605 while (isspace(*s)) s++;
606 if (*s=='\0')
607 exitfileerror(20, "unexpected end of line\n");
609 s2 = s + strlen(s);
610 while (isspace(*(s2-1))) s2--;
611 *s2 = '\0';
613 switch (namenum)
615 case 1: /* basename */
616 if (!inclass)
617 cfg->basename = strdup(s);
618 if (cl != NULL)
619 cl->basename = strdup(s);
620 break;
622 case 2: /* libbase */
623 if (inclass)
624 exitfileerror(20, "libbase not valid config option when in a class section\n");
625 cfg->libbase = strdup(s);
626 break;
628 case 3: /* libbasetype */
629 if (inclass)
630 exitfileerror(20, "libbasetype not valid config option when in a class section\n");
631 cfg->libbasetype = strdup(s);
632 break;
634 case 4: /* libbasetypeextern */
635 if (inclass)
636 exitfileerror(20, "libbasetype not valid config option when in a class section\n");
637 libbasetypeextern = strdup(s);
638 break;
640 case 5: /* version */
641 if (inclass)
642 exitfileerror(20, "version not valid config option when in a class section\n");
643 if (sscanf(s, "%u.%u", &cfg->majorversion, &cfg->minorversion)!=2)
644 exitfileerror(20, "wrong version string \"%s\"\n", s);
645 break;
647 case 6: /* date */
648 if (inclass)
649 exitfileerror(20, "date not valid config option when in a class section\n");
650 #ifndef _WIN32
651 if (strptime(s, "%e.%m.%Y", &date) == NULL)
653 exitfileerror(20, "date string has to have d.m.yyyy format\n");
655 #endif
656 cfg->datestring = strdup(s);
657 break;
659 case 7: /* copyright */
660 if (inclass)
661 exitfileerror(20, "copyright not valid config option when in a class section\n");
662 cfg->copyright = strdup(s);
663 break;
665 case 8: /* libcall */
666 fprintf(stderr, "libcall specification is deprecated and ignored\n");
667 break;
669 case 9: /* forcebase */
670 if (inclass)
671 exitfileerror(20, "forcebase not valid config option when in a class section\n");
672 slist_append(&cfg->forcelist, s);
673 break;
675 case 10: /* superclass */
676 if (cl == NULL)
677 exitfileerror(20, "superclass specified when not a BOOPSI class\n");
678 cl->superclass = strdup(s);
679 break;
681 case 11: /* superclass_field */
682 if (cl == NULL)
683 exitfileerror(20, "superclass_field specified when not a BOOPSI class\n");
684 cl->superclass_field = strdup(s);
685 break;
687 case 12: /* residentpri */
688 if (!inclass)
690 int count;
691 char dummy;
693 count = sscanf(s, "%d%c", &cfg->residentpri, &dummy);
694 if (count != 1 ||
695 cfg->residentpri < -128 || cfg->residentpri > 127
698 exitfileerror(20, "residentpri number format error\n");
701 else
702 exitfileerror(20, "residentpri not valid config option when in a class section\n");
703 break;
705 case 13: /* options */
706 if (!inclass)
708 static const char *optionnames[] =
710 "noautolib", "noexpunge", "noresident", "peropenerbase",
711 "peridbase", "includes", "noincludes", "nostubs",
712 "autoinit", "noautoinit", "resautoinit", "noopenclose",
713 "selfinit"
715 const unsigned int optionnums = sizeof(optionnames)/sizeof(char *);
716 int optionnum;
720 for (i = 0, optionnum = 0; optionnum==0 && i<optionnums; i++)
722 if (strncmp(s, optionnames[i], strlen(optionnames[i]))==0)
724 optionnum = i + 1;
725 s += strlen(optionnames[i]);
726 while (isspace(*s)) s++;
727 if (*s == ',')
728 s++;
729 else if (*s != '\0')
730 exitfileerror(20, "Unrecognized option\n");
733 if (optionnum == 0)
734 exitfileerror(20, "Unrecognized option\n");
735 switch (optionnum)
737 case 1: /* noautolib */
738 cfg->options |= OPTION_NOAUTOLIB;
739 break;
740 case 2: /* noexpunge */
741 cfg->options |= OPTION_NOEXPUNGE;
742 break;
743 case 3: /* noresident */
744 cfg->options |= OPTION_NORESIDENT;
745 cfg->firstlvo = 1;
746 break;
747 case 5: /* peridbase */
748 cfg->options |= OPTION_DUPPERID;
749 /* Fall through */
750 case 4: /* peropenerbase */
751 if (cfg->options & OPTION_DUPBASE)
752 exitfileerror(20, "Only one option peropenerbase or peridbase allowed\n");
753 cfg->options |= OPTION_DUPBASE;
754 break;
755 case 6: /* includes */
756 if (cfg->options & OPTION_NOINCLUDES)
757 exitfileerror(20, "option includes and noincludes are incompatible\n");
758 cfg->options |= OPTION_INCLUDES;
759 break;
760 case 7: /* noincludes */
761 if (cfg->options & OPTION_INCLUDES)
762 exitfileerror(20, "option includes and noincludes are incompatible\n");
763 cfg->options |= OPTION_NOINCLUDES;
764 break;
765 case 8: /* nostubs */
766 cfg->options |= OPTION_NOSTUBS;
767 break;
768 case 9: /* autoinit */
769 if (cfg->options & OPTION_NOAUTOINIT)
770 exitfileerror(20, "option autoinit and noautoinit are incompatible\n");
771 cfg->options |= OPTION_AUTOINIT;
772 break;
773 case 10: /* noautoinit */
774 if (cfg->options & OPTION_AUTOINIT)
775 exitfileerror(20, "option autoinit and noautoinit are incompatible\n");
776 cfg->options |= OPTION_NOAUTOINIT;
777 break;
778 case 11: /* resautoinit */
779 if (cfg->options & OPTION_SELFINIT)
780 exitfileerror(20, "option resautoinit and selfinit are incompatible\n");
781 cfg->options |= OPTION_RESAUTOINIT;
782 break;
783 case 12:
784 cfg->options |= OPTION_NOOPENCLOSE;
785 break;
786 case 13: /* noresautoinit */
787 if (cfg->options & OPTION_RESAUTOINIT)
788 exitfileerror(20, "option resautoinit and selfinit are incompatible\n");
789 cfg->options |= OPTION_SELFINIT;
790 break;
792 while (isspace(*s)) s++;
793 } while(*s !='\0');
795 else
797 static const char *optionnames[] =
799 "private"
801 const unsigned int optionnums = sizeof(optionnames)/sizeof(char *);
802 int optionnum;
806 for (i = 0, optionnum = 0; optionnum==0 && i<optionnums; i++)
808 if (strncmp(s, optionnames[i], strlen(optionnames[i]))==0)
810 optionnum = i + 1;
811 s += strlen(optionnames[i]);
812 while (isspace(*s)) s++;
813 if (*s == ',')
814 s++;
815 else if (*s != '\0')
816 exitfileerror(20, "Unrecognized option\n");
819 if (optionnum == 0)
820 exitfileerror(20, "Unrecognized option\n");
821 switch (optionnum)
823 case 1: /* private */
824 cl->options |= COPTION_PRIVATE;
825 break;
827 while (isspace(*s)) s++;
828 } while(*s !='\0');
830 break;
832 case 14: /* sysbase_field */
833 if (inclass)
834 exitfileerror(20, "sysbase_field not valid config option when in a class section\n");
835 cfg->sysbase_field = strdup(s);
836 break;
838 case 15: /* seglist_field */
839 if (inclass)
840 exitfileerror(20, "seglist_field not valid config option when in a class section\n");
841 cfg->seglist_field = strdup(s);
842 break;
844 case 16: /* rootbase_field */
845 if (inclass)
846 exitfileerror(20, "rootbase_field not valid config option when in a class section\n");
847 cfg->rootbase_field = strdup(s);
848 break;
850 case 17: /* classptr_field */
851 if (cl == NULL)
853 exitfileerror
856 "classptr_field specified when not a BOOPSI class\n"
859 cl->classptr_field = strdup(s);
860 break;
862 case 18: /* classptr_var */
863 if (cl == NULL)
865 exitfileerror
868 "classptr_var specified when not a BOOPSI class\n"
871 cl->classptr_var = strdup(s);
872 break;
874 case 19: /* classid */
875 if (cl == NULL)
876 exitfileerror(20, "classid specified when not a BOOPSI class\n");
877 if (cl->classid != NULL)
878 exitfileerror(20, "classid specified twice\n");
879 cl->classid = strdup(s);
880 if (strcmp(cl->classid, "NULL") == 0)
881 cl->options |= COPTION_PRIVATE;
882 break;
884 case 20: /* classdatatype */
885 if (cl == NULL)
886 exitfileerror(20, "classdatatype specified when not a BOOPSI class\n");
887 cl->classdatatype = strdup(s);
888 break;
890 case 21: /* beginio_func */
891 if (inclass)
892 exitfileerror(20, "beginio_func not valid config option when in a class section\n");
893 if (cfg->modtype != DEVICE)
894 exitfileerror(20, "beginio_func specified when not a device\n");
895 cfg->beginiofunc = strdup(s);
896 break;
898 case 22: /* abortio_func */
899 if (inclass)
900 exitfileerror(20, "abortio_func not valid config option when in a class section\n");
901 if (cfg->modtype != DEVICE)
902 exitfileerror(20, "abortio_func specified when not a device\n");
903 cfg->abortiofunc = strdup(s);
904 break;
906 case 23: /* dispatcher */
907 if (cl == NULL)
908 exitfileerror(20, "dispatcher specified when not a BOOPSI class\n");
909 cl->dispatcher = strdup(s);
910 /* function references are not needed when dispatcher is specified */
911 cfg->intcfg |= CFG_NOREADFUNCS;
912 break;
914 case 24: /* initpri */
915 if (cl != NULL)
917 int count;
918 char dummy;
920 count = sscanf(s, "%d%c", &cl->initpri, &dummy);
921 if (count != 1 ||
922 cl->initpri < -128 || cl->initpri > 127
925 exitfileerror(20, "initpri number format error\n");
928 else
929 exitfileerror(20, "initpri only valid config option for a BOOPSI class\n");
930 break;
932 case 25: /* type */
933 if (!inclass)
934 exitfileerror(20, "type only valid config option in a class section\n");
935 if (strcmp(s,"mcc")==0)
936 cl->classtype = MCC;
937 else if (strcmp(s,"mui")==0)
938 cl->classtype = MUI;
939 else if (strcmp(s,"mcp")==0)
940 cl->classtype = MCP;
941 else if (strcmp(s, "image")==0)
942 cl->classtype = IMAGE;
943 else if (strcmp(s, "gadget")==0)
944 cl->classtype = GADGET;
945 else if (strcmp(s, "datatype")==0)
946 cl->classtype = DATATYPE;
947 else if (strcmp(s, "usbclass")==0)
948 cl->classtype = USBCLASS;
949 else if (strcmp(s, "class")==0)
950 cl->classtype = CLASS;
951 else if (strcmp(s, "hidd")==0)
952 cl->classtype = HIDD;
953 else
955 fprintf(stderr, "Unknown type \"%s\" specified\n", s);
956 exit(20);
958 break;
959 case 26: /* getidfunc */
960 cfg->getidfunc = strdup(s);
961 break;
963 case 27: /* addromtag */
964 cfg->addromtag = strdup(s);
965 break;
968 else /* Line starts with ## */
970 s = line+2;
971 while (isspace(*s)) s++;
972 if (strncmp(s, "end", 3)!=0)
973 exitfileerror(20, "\"##end config\" expected\n");
975 s += 3;
976 if (!isspace(*s))
977 exitfileerror(20, "\"##end config\" expected\n");
979 while (isspace(*s)) s++;
980 if (strncmp(s, "config", 6)!=0)
981 exitfileerror(20, "\"##end config\" expected\n");
983 s += 6;
984 while (isspace(*s)) s++;
985 if (*s!='\0')
986 exitfileerror(20, "\"##end config\" expected\n");
988 atend = 1;
992 /* When not in a class section fill in default values for fields in cfg */
993 if (!inclass)
995 if (cfg->basename==NULL)
997 cfg->basename = strdup(cfg->modulename);
998 *cfg->basename = toupper(*cfg->basename);
1000 if (cfg->libbase==NULL)
1002 unsigned int len = strlen(cfg->basename)+5;
1003 cfg->libbase = malloc(len);
1004 snprintf(cfg->libbase, len, "%sBase", cfg->basename);
1006 if (cfg->libbasetype == NULL && libbasetypeextern != NULL)
1007 cfg->libbasetype = strdup(libbasetypeextern);
1008 if (cfg->sysbase_field != NULL && cfg->libbasetype == NULL)
1009 exitfileerror(20, "sysbase_field specified when no libbasetype is given\n");
1010 if (cfg->seglist_field != NULL && cfg->libbasetype == NULL)
1011 exitfileerror(20, "seglist_field specified when no libbasetype is given\n");
1012 /* rootbase_field only allowed when duplicating base */
1013 if (cfg->rootbase_field != NULL && !(cfg->options & OPTION_DUPBASE))
1014 exitfileerror(20, "rootbasefield only valid for option peropenerbase or peridbase\n");
1015 if (cfg->getidfunc != NULL && !(cfg->options & OPTION_DUPPERID))
1016 exitfileerror(20, "getidfunc only valid for option peridbase\n");
1018 /* Set default date to current date */
1019 if (cfg->datestring == NULL)
1021 char tmpbuf[256];
1022 time_t now = time(NULL);
1023 struct tm *ltime = localtime(&now);
1025 snprintf(tmpbuf, sizeof(tmpbuf), "%u.%u.%u",
1026 ltime->tm_mday, 1 + ltime->tm_mon, 1900 + ltime->tm_year);
1028 cfg->datestring = strdup(tmpbuf);
1031 if (cfg->copyright == NULL)
1032 cfg->copyright = "";
1034 if ( (cfg->beginiofunc != NULL && cfg->abortiofunc == NULL)
1035 || (cfg->beginiofunc == NULL && cfg->abortiofunc != NULL)
1037 exitfileerror(20, "please specify both beginio_func and abortio_func\n");
1039 if (libbasetypeextern==NULL)
1041 switch (cfg->modtype)
1043 case DEVICE:
1044 cfg->libbasetypeptrextern = "struct Device *";
1045 break;
1046 case RESOURCE:
1047 cfg->libbasetypeptrextern = "APTR ";
1048 break;
1049 case LIBRARY:
1050 case MUI:
1051 case MCP:
1052 case MCC:
1053 case GADGET:
1054 case DATATYPE:
1055 case USBCLASS:
1056 case HIDD:
1057 cfg->libbasetypeptrextern = "struct Library *";
1058 break;
1059 default:
1060 fprintf(stderr, "Internal error: Unsupported modtype for libbasetypeptrextern\n");
1061 exit(20);
1064 else
1066 cfg->libbasetypeptrextern = malloc(strlen(libbasetypeextern)+3);
1067 strcpy(cfg->libbasetypeptrextern, libbasetypeextern);
1068 strcat(cfg->libbasetypeptrextern, " *");
1069 free(libbasetypeextern);
1073 /* When class was given too fill in some defaults when not specified */
1074 if (cl != NULL)
1076 if (cl->classtype == UNSPECIFIED)
1077 cl->classtype = CLASS;
1079 if (cl->basename == NULL)
1081 if (!inclass)
1082 cl->basename = cfg->basename;
1083 else
1084 exitfileerror(20, "basename has to be specified in the config section inside of a class section\n");
1087 /* MUI classes are always private */
1088 if (cl->classtype == MUI || cl->classtype == MCC || cl->classtype == MCP)
1089 cl->options |= COPTION_PRIVATE;
1091 if (cl->classid == NULL
1092 && (cl->classtype != MUI && cl->classtype != MCC && cl->classtype != MCP)
1095 if (cl->classtype == HIDD)
1097 cl->options &= !COPTION_PRIVATE;
1099 else if (cl->options & COPTION_PRIVATE)
1101 cl->classid = "NULL";
1103 else
1105 char s[256] = "";
1107 if (cl->classtype == GADGET || cl->classtype == IMAGE || cl->classtype == CLASS || cl->classtype == USBCLASS)
1109 sprintf(s, "\"%sclass\"", inclass ? cl->basename : cfg->modulename);
1111 else if (cl->classtype == DATATYPE)
1113 sprintf(s, "\"%s.datatype\"", inclass ? cl->basename : cfg->modulename);
1115 cl->classid = strdup(s);
1119 /* Only specify superclass or superclass_field */
1120 if (cl->superclass != NULL && cl->superclass_field != NULL)
1121 exitfileerror(20, "Only specify one of superclass or superclass_field in config section\n");
1123 /* Give default value to superclass if it is not specified */
1124 if (cl->superclass == NULL && cl->superclass == NULL)
1126 switch (cl->classtype)
1128 case MUI:
1129 case MCC:
1130 cl->superclass = "MUIC_Area";
1131 break;
1132 case MCP:
1133 cl->superclass = "MUIC_Mccprefs";
1134 break;
1135 case IMAGE:
1136 cl->superclass = "IMAGECLASS";
1137 break;
1138 case GADGET:
1139 cl->superclass = "GADGETCLASS";
1140 break;
1141 case DATATYPE:
1142 cl->superclass = "DATATYPESCLASS";
1143 break;
1144 case CLASS:
1145 cl->superclass = "ROOTCLASS";
1146 break;
1147 case HIDD:
1148 cl->superclass = "CLID_Root";
1149 break;
1150 default:
1151 exitfileerror(20, "Internal error: unhandled classtype in readsectionconfig\n");
1152 break;
1158 static void readsectioncdef(struct config *cfg)
1160 int atend = 0;
1161 char *line, *s;
1163 while (!atend)
1165 line = readline();
1166 if (line==NULL)
1167 exitfileerror(20, "unexptected end of file in section cdef\n");
1169 if (strncmp(line, "##", 2)!=0)
1171 slist_append(&cfg->cdeflines, line);
1173 else
1175 s = line+2;
1176 while (isspace(*s)) s++;
1177 if (strncmp(s, "end", 3)!=0)
1178 exitfileerror(20, "\"##end cdef\" expected\n");
1180 s += 3;
1181 while (isspace(*s)) s++;
1182 if (strncmp(s, "cdef", 4)!=0)
1183 exitfileerror(20, "\"##end cdef\" expected\n");
1185 s += 5;
1186 while (isspace(*s)) s++;
1187 if (*s!='\0')
1188 exitfileerror(20, "unexpected character at position %d\n");
1190 atend = 1;
1195 static void readsectioncdefprivate(struct config *cfg)
1197 int atend = 0;
1198 char *line, *s;
1200 while (!atend)
1202 line = readline();
1203 if (line==NULL)
1204 exitfileerror(20, "unexptected end of file in section cdef\n");
1206 if (strncmp(line, "##", 2)!=0)
1208 slist_append(&cfg->cdefprivatelines, line);
1210 else
1212 s = line+2;
1213 while (isspace(*s)) s++;
1214 if (strncmp(s, "end", 3)!=0)
1215 exitfileerror(20, "\"##end cdefprivate\" expected\n");
1217 s += 3;
1218 while (isspace(*s)) s++;
1219 if (strncmp(s, "cdefprivate", 11)!=0)
1220 exitfileerror(20, "\"##end cdefprivate\" expected\n");
1222 s += 11;
1223 while (isspace(*s)) s++;
1224 if (*s!='\0')
1225 exitfileerror(20, "unexpected character at position %d\n");
1227 atend = 1;
1232 static void readsectionstartup(struct config *cfg)
1234 int atend = 0;
1235 char *line, *s;
1237 while (!atend)
1239 line = readline();
1240 if (line==NULL)
1241 exitfileerror(20, "unexptected end of file in section startup\n");
1243 if (strncmp(line, "##", 2)!=0)
1245 slist_append(&cfg->startuplines, line);
1247 else
1249 s = line+2;
1250 while (isspace(*s)) s++;
1251 if (strncmp(s, "end", 3)!=0)
1252 exitfileerror(20, "\"##end startup\" expected\n");
1254 s += 3;
1255 while (isspace(*s)) s++;
1256 if (strncmp(s, "startup", 7)!=0)
1257 exitfileerror(20, "\"##end startup\" expected\n");
1259 s += 7;
1260 while (isspace(*s)) s++;
1261 if (*s!='\0')
1262 exitfileerror(20, "unexpected character at position %d\n");
1264 atend = 1;
1269 static void readsectionfunctionlist(struct config *cfg)
1271 int atend = 0, i;
1272 char *line, *s, *s2;
1273 unsigned int lvo = cfg->firstlvo;
1274 struct functionhead **funclistptr = &cfg->funclist;
1276 if (cfg->basename==NULL)
1277 exitfileerror(20, "section functionlist has to come after section config\n");
1279 while (!atend)
1281 line = readline();
1282 if (line==NULL)
1283 exitfileerror(20, "unexptected EOF in functionlist section\n");
1284 if (strlen(line)==0)
1286 if (*funclistptr != NULL)
1287 funclistptr = &((*funclistptr)->next);
1288 lvo++;
1290 else if (isspace(*line))
1292 s = line;
1293 while (isspace(*s)) s++;
1294 if (*s=='\0')
1296 if (*funclistptr != NULL)
1297 funclistptr = &((*funclistptr)->next);
1298 lvo++;
1300 else
1301 exitfileerror(20, "no space allowed before functionname\n");
1303 else if (strncmp(line, "##", 2)==0)
1305 s = line+2;
1306 while (isspace(*s)) s++;
1307 if (strncmp(s, "end", 3)!=0)
1308 exitfileerror(20, "\"##end functionlist\" expected\n");
1310 s += 3;
1311 while (isspace(*s)) s++;
1312 if (strncmp(s, "functionlist", 12)!=0)
1313 exitfileerror(20, "\"##end functionlist\" expected\n");
1315 s += 12;
1316 while (isspace(*s)) s++;
1317 if (*s!='\0')
1318 exitfileerror(20, "unexpected character on position %d\n", s-line);
1320 atend = 1;
1322 else if (*line=='.')
1324 s = line+1;
1325 if (strncmp(s, "skip", 4)==0)
1327 int n;
1329 s += 4;
1330 if (!isspace(*s))
1331 exitfileerror(20, "syntax is '.skip n'\n");
1333 n=strtol(s, &s2, 10);
1334 if (s2==NULL)
1335 exitfileerror(20, "positive number expected\n");
1337 while (isspace(*s2)) s2++;
1338 if ((*s2 != '\0') && (*s2 != '#'))
1339 exitfileerror(20, "syntax is '.skip n'\n");
1340 if (*funclistptr != NULL)
1341 funclistptr = &((*funclistptr)->next);
1342 lvo += n;
1344 else if (strncmp(s, "alias", 5)==0)
1346 s += 5;
1348 if (!isspace(*s))
1349 exitfileerror(20, "syntax is '.alias name'\n");
1351 while (isspace(*s)) s++;
1352 if (*s == '\0' || !(isalpha(*s) || *s == '_'))
1353 exitfileerror(20, "syntax is '.alias name'\n");
1355 s2 = s;
1356 s++;
1357 while (isalnum(*s) || *s == '_') s++;
1359 if (isspace(*s))
1361 *s = '\0';
1362 do {
1363 s++;
1364 } while (isspace(*s));
1367 if (*s != '\0')
1368 exitfileerror(20, "syntax is '.alias name'\n");
1370 if (*funclistptr == NULL)
1371 exitfileerror(20, ".alias has to come after a function declaration\n");
1373 slist_append(&(*funclistptr)->aliases, s2);
1375 else if (strncmp(s, "function", 8) == 0)
1377 s += 8;
1379 if (!isspace(*s))
1380 exitfileerror(20, "Syntax error\n");
1382 while (isspace(*s)) s++;
1383 if (*s == '\0' || !(isalpha(*s) || *s == '_'))
1384 exitfileerror(20, "syntax is '.function name'\n");
1386 s2 = s;
1387 s++;
1388 while (isalnum(*s) || *s == '_') s++;
1390 if (isspace(*s))
1392 *s = '\0';
1393 do {
1394 s++;
1395 } while (isspace(*s));
1398 if (*s != '\0')
1399 exitfileerror(20, "syntax is '.function name'\n");
1401 if (*funclistptr == NULL)
1402 exitfileerror(20, ".function has to come after a function declaration\n");
1404 funcsetinternalname(*funclistptr, s2);
1406 else if (strncmp(s, "cfunction", 9)==0)
1408 if (*funclistptr == NULL)
1409 exitfileerror(20, ".cfunction has to come after a function declaration\n");
1411 (*funclistptr)->libcall = REGISTER;
1413 else if (strncmp(s, "private", 7)==0)
1415 if (*funclistptr == NULL)
1416 exitfileerror(20, ".private has to come after a function declaration\n");
1418 (*funclistptr)->priv = 1;
1420 else if (strncmp(s, "novararg", 8)==0)
1422 if (*funclistptr == NULL)
1423 exitfileerror(20, ".novararg has to come after a function declaration\n");
1425 (*funclistptr)->novararg = 1;
1427 else
1428 exitfileerror(20, "Syntax error");
1430 else if (*line!='#') /* Ignore line that is a comment, e.g. that starts with a # */
1432 /* The line is a function prototype. It can have two syntax
1433 * type funcname(argproto1, argproto2, ...)
1434 * type funcname(argproto1, argproto2, ...) (reg1, reg2, ...)
1435 * The former is for C type function argument passing, the latter for
1436 * register argument passing.
1438 char c, *args[64], *regs[64], *funcname;
1439 int len, argcount = 0, regcount = 0, brcount = 0;
1441 /* Parse 'type functionname' at the beginning of the line */
1442 s = strchr(line, '(');
1443 if (s == NULL)
1444 exitfileerror(20, "( expected at position %d\n", strlen(line) + 1);
1446 s2 = s;
1447 while (isspace(*(s2-1)))
1448 s2--;
1449 *s2 = '\0';
1451 while (s2 > line && !isspace(*(s2-1)) && !(*(s2-1) == '*'))
1452 s2--;
1454 if (s2 == line)
1455 exitfileerror(20, "No type specifier before function name\n");
1457 if (*funclistptr != NULL)
1458 funclistptr = &((*funclistptr)->next);
1459 *funclistptr = newfunctionhead(s2, STACK);
1461 while (isspace(*(s2-1)))
1462 s2--;
1463 *s2 = '\0';
1464 (*funclistptr)->type = strdup(line);
1465 (*funclistptr)->lvo = lvo;
1466 lvo++;
1468 /* Parse function prototype */
1469 s++;
1470 while (isspace(*s))
1471 s++;
1472 c = *s;
1474 while (c != ')')
1476 while (isspace(*s))
1477 s++;
1479 args[argcount] = s;
1480 argcount++;
1482 while
1484 *s != '\0'
1485 && !(brcount == 0 && (*s == ',' || *s == ')'))
1488 if (*s == '(')
1489 brcount++;
1490 if (*s == ')')
1492 if (brcount > 0)
1493 brcount--;
1494 else
1495 exitfileerror(20, "Unexected ')' at position %d\n", s-line+1);
1497 s++;
1500 c = *s;
1501 if (c == '\0')
1502 exitfileerror(20, "'(' without ')'");
1504 s2 = s;
1505 while (isspace(*(s2-1)))
1506 s2--;
1507 *s2 = '\0';
1509 if (!(s2 > args[argcount - 1]))
1510 exitfileerror(20, "Syntax error in function prototype\n");
1512 s++;
1515 s++;
1516 while (*s != '\0' && isspace(*s))
1517 s++;
1519 if (*s == '(')
1521 /* Parse registers specifications if available otherwise this prototype for C type argument passing */
1523 /* There may be no register specified with () so be sure then c is == ')' */
1524 s++;
1525 while(isspace(*s))
1526 s++;
1528 c = *s;
1530 while (c != ')')
1532 while (isspace(*s))
1533 s++;
1535 regs[regcount] = s;
1536 regcount++;
1538 if (memchr("AD",s[0],2)!=NULL && memchr("01234567",s[1],8)!=NULL)
1540 s += 2;
1541 c = *s;
1542 if (c == '/')
1544 s++;
1545 if (s[0] == s[-3] && s[1] == s[-2] + 1)
1547 s += 2;
1548 c = *s;
1550 else
1551 exitfileerror(20,
1552 "wrong register specification \"%s\" for argument %u\n",
1553 regs[regcount-1], regcount
1556 if (regcount > 2)
1557 exitfileerror(20, "maximum two arguments passed in two registers allowed\n");
1559 *s = '\0';
1561 else
1562 exitfileerror(20,
1563 "wrong register \"%s\" for argument %u\n",
1564 regs[regcount-1], regcount
1567 while (isspace(c))
1569 s++;
1570 c = *s;
1572 if (c == '\0')
1573 exitfileerror(20, "'(' without ')'\n");
1574 if (c != ',' && c != ')')
1575 exitfileerror(20, "',' or ')' expected at position %d\n", s-line+1);
1577 s++;
1580 s++;
1581 while (isspace(*s)) s++;
1582 if (*s!='\0')
1583 exitfileerror(20, "wrong char '%c' at position %d\n", *s, (int)(s-line) + 1);
1585 if (argcount != regcount)
1586 exitfileerror(20, "Number of arguments (%d) and registers (%d) mismatch\n",
1587 argcount, regcount
1590 (*funclistptr)->libcall = REGISTERMACRO;
1591 for (i = 0; i < argcount; i++)
1592 funcaddarg(*funclistptr, args[i], regs[i]);
1594 else if (*s == '\0')
1595 { /* No registers specified */
1596 for (i = 0; i < argcount; i++)
1597 funcaddarg(*funclistptr, args[i], NULL);
1599 else
1600 exitfileerror(20, "wrong char '%c' at position %d\n", *s, (int)(s-line) + 1);
1605 static void readsectionmethodlist(struct classinfo *cl)
1607 int atend = 0, i;
1608 char *line, *s, *s2;
1609 struct functionhead **methlistptr = &cl->methlist;
1610 struct stringlist *interface = NULL;
1612 if (cl->basename==NULL)
1613 exitfileerror(20, "section methodlist has to come after section config\n");
1615 while (!atend)
1617 line = readline();
1618 if (line==NULL)
1619 exitfileerror(20, "unexptected EOF in methodlist section\n");
1621 /* Ignore empty lines or lines that qre a comment, e.g. that starts with a # */
1622 if (strlen(line)==0 || (line[0] == '#' && line[1] != '#'))
1623 continue;
1625 if (isspace(*line))
1626 exitfileerror(20, "No space allowed at start of the line\n");
1628 if (strncmp(line, "##", 2)==0) /* Is this the end ? */
1630 s = line+2;
1631 while (isspace(*s)) s++;
1632 if (strncmp(s, "end", 3)!=0)
1633 exitfileerror(20, "\"##end methodlist\" expected\n");
1635 s += 3;
1636 while (isspace(*s)) s++;
1637 if (strncmp(s, "methodlist", 10)!=0)
1638 exitfileerror(20, "\"##end methodlist\" expected\n");
1640 s += 10;
1641 while (isspace(*s)) s++;
1642 if (*s!='\0')
1643 exitfileerror(20, "unexpected character on position %d\n", s-line);
1645 atend = 1;
1647 continue;
1650 if (*line=='.')
1652 s = line+1;
1653 if (strncmp(s, "alias", 5)==0)
1655 s += 5;
1657 if (!isspace(*s))
1658 exitfileerror(20, "syntax is '.alias name'\n");
1660 while (isspace(*s)) s++;
1661 if (*s == '\0' || !(isalpha(*s) || *s == '_'))
1662 exitfileerror(20, "syntax is '.alias name'\n");
1664 s2 = s;
1665 s++;
1666 while (isalnum(*s) || *s == '_') s++;
1668 if (isspace(*s))
1670 *s = '\0';
1671 do {
1672 s++;
1673 } while (isspace(*s));
1676 if (*s != '\0')
1677 exitfileerror(20, "syntax is '.alias name'\n");
1679 if (*methlistptr == NULL)
1680 exitfileerror(20, ".alias has to come after a function declaration\n");
1682 slist_append(&(*methlistptr)->aliases, s2);
1684 else if (strncmp(s, "function", 8) == 0)
1686 s += 8;
1688 if (!isspace(*s))
1689 exitfileerror(20, "Syntax error\n");
1691 while (isspace(*s)) s++;
1692 if (*s == '\0' || !(isalpha(*s) || *s == '_'))
1693 exitfileerror(20, "syntax is '.function name'\n");
1695 s2 = s;
1696 s++;
1697 while (isalnum(*s) || *s == '_') s++;
1699 if (isspace(*s))
1701 *s = '\0';
1702 do {
1703 s++;
1704 } while (isspace(*s));
1707 if (*s != '\0')
1708 exitfileerror(20, "syntax is '.function name'\n");
1710 if (*methlistptr == NULL)
1711 exitfileerror(20, ".function has to come after a function declaration\n");
1713 funcsetinternalname(*methlistptr, s2);
1715 else if (strncmp(s, "interface", 9) == 0)
1717 if (cl->classtype != HIDD)
1718 exitfileerror(20, "interface only valid for a HIDD\n");
1720 s += 9;
1722 if (!isspace(*s))
1723 exitfileerror(20, "Syntax error\n");
1725 while (isspace(*s)) s++;
1726 if (*s == '\0' || !isalpha(*s))
1727 exitfileerror(20, "syntax is '.interface name'\n");
1729 s2 = s;
1730 s++;
1731 while (isalnum(*s) || *s == '_') s++;
1733 if (isspace(*s))
1735 *s = '\0';
1736 do {
1737 s++;
1738 } while (isspace(*s));
1741 if (*s != '\0')
1742 exitfileerror(20, "syntax is '.interface name'\n");
1744 interface = slist_append(&cl->interfaces, s2);
1746 else
1747 exitfileerror(20, "Syntax error");
1749 else if (isalpha(*line))
1751 char stmp[256];
1753 for (s = line + 1; isalnum(*s) || *s == '_'; s++)
1756 if (cl->classtype == HIDD && interface == NULL)
1757 exitfileerror(20, "For a HIDD the first method has to come after an .interface line\n");
1759 if (*s != '\0')
1760 exitfileerror(20, "Only letters, digits and an underscore allowed in a methodname\n");
1762 if (*methlistptr != NULL)
1763 methlistptr = &((*methlistptr)->next);
1764 if (cl->classtype != HIDD)
1766 if (snprintf(stmp, 256, "%s__%s", cl->basename, line) >= 256)
1767 exitfileerror(20, "Method name too large\n");
1769 *methlistptr = newfunctionhead(stmp, STACK);
1770 (*methlistptr)->type = "IPTR";
1771 funcaddarg(*methlistptr, "Class *cl", NULL);
1772 funcaddarg(*methlistptr, "Object *o", NULL);
1773 funcaddarg(*methlistptr, "Msg msg", NULL);
1775 else
1777 if (snprintf(stmp, 256, "%s__%s__%s", cl->basename, interface->s, line) >= 256)
1778 exitfileerror(20, "Method name too large\n");
1780 *methlistptr = newfunctionhead(stmp, STACK);
1781 (*methlistptr)->type = "IPTR";
1782 funcaddarg(*methlistptr, "OOP_Class *cl", NULL);
1783 funcaddarg(*methlistptr, "OOP_Object *o", NULL);
1784 funcaddarg(*methlistptr, "OOP_Msg msg", NULL);
1785 (*methlistptr)->interface = interface;
1786 if (snprintf(stmp, 256, "mo%s_%s", interface->s, line) >= 256)
1787 exitfileerror(20, "Method name too large\n");
1788 (*methlistptr)->method = strdup(stmp);
1790 slist_append(&(*methlistptr)->aliases, line);
1792 else
1793 exitfileerror(20, "Methodname has to begin with a letter\n");
1797 static void
1798 readsectionclass(struct config *cfg)
1800 char *s;
1801 struct classinfo *cl;
1803 cl = newclass(cfg);
1804 s = readsections(cfg, cl, 1);
1805 if (s == NULL)
1806 exitfileerror(20, "Unexpected end of file\n");
1808 if (strncmp(s, "##", 2) != 0)
1809 exitfileerror(20, "'##end class' expected\n");
1810 s += 2;
1812 while (isspace(*s)) s++;
1814 if (strncmp(s, "end", 3) != 0)
1815 exitfileerror(20, "'##end class' expected\n");
1816 s += 3;
1818 if (!isspace(*s))
1819 exitfileerror(20, "'##end class' expected\n");
1820 while (isspace(*s)) s++;
1822 if (strncmp(s, "class", 5) != 0)
1823 exitfileerror(20, "'##end class' expected\n");
1824 s += 5;
1826 while (isspace(*s)) s++;
1827 if (*s != '\0')
1828 exitfileerror(20, "'##end class' expected\n");
1831 static struct classinfo *newclass(struct config *cfg)
1833 struct classinfo *cl, *classlistit;
1835 cl = malloc(sizeof(struct classinfo));
1836 if (cl == NULL)
1838 fprintf(stderr, "Out of memory\n");
1839 exit(20);
1841 memset(cl, 0, sizeof(struct classinfo));
1843 /* By default the classes are initialized with a priority of 1 so they
1844 * are initialized before any user added initialization with priority 1
1846 cl->initpri = 1;
1848 if (cfg->classlist == NULL)
1849 cfg->classlist = cl;
1850 else
1854 classlistit = cfg->classlist;
1855 classlistit->next != NULL;
1856 classlistit = classlistit->next
1859 classlistit->next = cl;
1862 return cl;