1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11 
12 
13 #include <stdio.h>
14 #include <ctype.h>
15 #include <stdarg.h>
16 #include <string.h>
17 
18 #include "lex.h"
19 #include "DXStrings.h"
20 
21 #include "ParseMDF.h"
22 
23 #include "DXType.h"
24 #include "NodeDefinition.h"
25 #include "ParameterDefinition.h"
26 #include "Dictionary.h"
27 #include "NDAllocatorDictionary.h"
28 #include "ErrorDialogManager.h"
29 
30 
31 /***
32  *** State constants:
33  ***/
34 
35 #define ST_NONE			0
36 #define ST_MODULE		1
37 #define ST_CATEGORY		2
38 #define ST_DESCRIPTION		4
39 #define ST_INPUT		8
40 #define ST_REPEAT	 	16
41 #define ST_OUTPUT		32
42 #define ST_ERROR		64
43 #define ST_SAW_REPEAT		128
44 #define ST_FLAGS		256
45 #define ST_OUTBOARD		512
46 #define ST_LOADABLE		1024
47 #define ST_PACKAGE		2048
48 #define ST_OPTIONS		4096
49 
50 
51 #ifdef NOT_YET
52 /***
53  *** Static pointer to MDF (for sorting purposes)
54  ***/
55 static Dictionary* _mdf;
56 #endif
57 
58 Dictionary *theDynamicPackageDictionary = new Dictionary;
59 
60 /*****************************************************************************/
61 /* _ParsePackageLine -						     */
62 /*                                                                           */
63 /* Parses and processes the PACKAGE line.				     */
64 /*                                                                           */
65 /*****************************************************************************/
66 
67 static
_ParsePackageLine(char * line,int lineNumber,int start)68 boolean _ParsePackageLine(char*      line,
69 			    int        lineNumber,
70 			    int        start)
71 {
72     char *begin, *end;
73 
74     ASSERT(line);
75     ASSERT(lineNumber > 0);
76     ASSERT(start >= 0);
77 
78     begin = &line[start];
79 
80     /*
81      * Skip space.
82      */
83     SkipWhiteSpace(begin);
84 
85     /*
86      * Parse package name.
87      */
88     end = begin;
89     while (*end && !IsWhiteSpace(end) && (*end != '\n') && (*end != '\r'))
90 	end++;
91     if (*end)
92 	end--;
93 
94     if  (end == begin)
95 	goto error;
96 
97     *end = '\0';
98     theDynamicPackageDictionary->replaceDefinition(
99 		(const char*)begin,
100 		(const void*) NULL);
101 
102     return TRUE;
103 
104 error:
105     return FALSE;
106 }
107 /*****************************************************************************/
108 /* _ParseModuleLine -						     */
109 /*                                                                           */
110 /* Parses and processes the MODULE line.				     */
111 /*                                                                           */
112 /*****************************************************************************/
113 
114 static
_ParseModuleLine(Dictionary * mdf,char * line,int lineNumber,int start)115 NodeDefinition *_ParseModuleLine(Dictionary    *mdf,
116 			    char*      line,
117 			    int        lineNumber,
118 			    int        start)
119 {
120     int current;
121     int temp;
122     char *function;
123     NodeDefinition *module = NUL(NodeDefinition*);
124 
125     ASSERT(mdf != NUL(Dictionary*));
126     ASSERT(line);
127     ASSERT(lineNumber > 0);
128     ASSERT(start >= 0);
129 
130     current = start;
131 
132     /*
133      * Skip space.
134      */
135     SkipWhiteSpace(line,current);
136 
137     /*
138      * Parse module name.
139      */
140     temp = current;
141     if (NOT IsRestrictedIdentifier(line, temp) ||
142 	    (temp != STRLEN(line) && !IsWhiteSpace(line, temp)))
143     {
144 	ErrorMessage("Invalid %s: %s must start with a letter and contain "
145 		     "only letters and numbers (file %s line %d)",
146 	    "module name", line + current, "MDF", lineNumber);
147  	goto error;
148     }
149 
150     /*
151      * Extract the module name.
152      */
153     function = &line[current];
154 
155     /*
156      * Look to see if the module has already been defined.
157      * remember the name index.
158      */
159     if (mdf->findDefinition(function))
160     {
161 	ErrorMessage
162 	    ("Encountered another definition of module \"%s\" on line %d.",
163 	     function,
164 	     lineNumber);
165 
166     	goto error;
167     }
168 
169     //
170     // Get a new NodeDefinition by name
171     //
172     module = theNDAllocatorDictionary->allocate(function);
173     if (!module) {
174 	ErrorMessage("Can not find NodeDefinition allocator for module '%s'",
175 				function);
176 	    goto error;
177     }
178     module->setName(function);
179 
180     return module;
181 
182 error:
183     if (module) delete module;
184     return NUL(NodeDefinition*);
185 }
186 
187 
188 #ifdef NOT_NEEDED
189 /*****************************************************************************/
190 /* _ParseCategoryLine -						     */
191 /*                                                                           */
192 /* Parses and processes the CATEGORY line.				     */
193 /*                                                                           */
194 /*****************************************************************************/
195 
196 static
_ParseCategoryLine(Dictionary * mdf,NodeDefinition * module,char * line,int lineNumber,int start)197 boolean _ParseCategoryLine(Dictionary*    mdf,
198 			      NodeDefinition* module,
199 			      char*      line,
200 			      int        lineNumber,
201 			      int        start)
202 {
203     int current;
204     int temp;
205 
206     ASSERT(mdf != NUL(Dictionary*));
207     ASSERT(module != NUL(NodeDefinition*));
208     ASSERT(line);
209     ASSERT(lineNumber > 0);
210     ASSERT(start >= 0);
211 
212     current = start;
213 
214     return TRUE;
215 }
216 
217 #endif // NOT_NEEDED
218 
ParseMDFTypes(ParameterDefinition * param,char * p,int lineNumber)219 boolean ParseMDFTypes(ParameterDefinition *param, char *p, int lineNumber)
220 {
221     char buffer[1000];
222     char *q;
223     int current;
224     char      save;
225     DXType	*input_type = NULL;
226     Type	type;
227 
228     /*
229      * Begin a new type.
230      */
231     current = 0;
232 
233     SkipWhiteSpace(p);
234 
235     while(*p != '\0')
236     {
237 	/*
238 	 * Demarcate a token.
239 	 */
240 	for (q = p; *q != ' ' AND *q != '\t' AND *q != '\0'; q++)
241 	    buffer[current++] = *q;
242 	buffer[current++] = ' ';
243 
244 	save = *q;
245 	*q   = '\0';
246 
247 	if (EqualString(p, "or"))
248 	{
249 	    /*
250 	     * Back up and erase " or " substring from end of buffer.
251 	     */
252 	    current -= 4;
253 
254 	    /*
255 	     * Find a matching type.
256 	     */
257 	    buffer[current] = '\0';
258 	    if ((type = DXType::StringToType(buffer)) == DXType::UndefinedType)
259 	    {
260 		ErrorMessage
261 		    ("Erroneous parameter type encountered in line %d.",
262 		     lineNumber);
263 		if (input_type)
264 		    delete input_type;
265 		return FALSE;
266 	    }
267 
268 	    /*
269 	     * Begin a new type and the type to the param list of type.
270 	     */
271             input_type = new DXType(type);
272 	    boolean r = param->addType(input_type);
273 	    ASSERT(r);
274 	    input_type = NUL(DXType*);
275 
276 	    current = 0;
277 	}
278 
279 	/*
280 	 * Restore the saved character and skip space.
281 	 */
282 	*q = save;
283 	p = q;
284 	SkipWhiteSpace(p);
285     }
286 
287     /*
288      * Find a matching type.
289      */
290     buffer[--current] = '\0';
291     if ((type = DXType::StringToType(buffer)) == DXType::UndefinedType)
292     {
293 	ErrorMessage ("Erroneous parameter type encountered in line %d.",
294 	     lineNumber);
295 	if (input_type)
296 	    delete input_type;
297 	return FALSE;
298     }
299     /*
300      * Begin a new type and add the type to the input list of type.
301      */
302     input_type = new DXType(type);
303     boolean r  = param->addType(input_type);
304     ASSERT(r);
305 
306     return TRUE;
307 }
308 
309 /*****************************************************************************/
310 
311 //
312 // Parse 'attribute:%d' from the given line.
313 // Return TRUE on success and set *val to %d.
314 //
GetIntegerAttribute(const char * line,const char * attr,int * val)315 static boolean GetIntegerAttribute(const char *line, const char *attr,
316 					int *val)
317 {
318     const char *c = strstr(line,attr);
319     if (!c)
320 	return FALSE;
321     c += STRLEN(attr);
322     while (*c && *c != ':') c++;
323     if (!*c)
324 	return FALSE;
325     c++;
326     *val = atoi(c);
327     return TRUE;
328 }
329 
_ParseParameterAttributes(ParameterDefinition * pd,const char * attr)330 boolean _ParseParameterAttributes(ParameterDefinition *pd , const char *attr)
331 {
332     int val;
333     boolean v;
334 
335     if (GetIntegerAttribute(attr,"private",&val)) {
336 	v = (val == 1 ? FALSE : TRUE);
337 	pd->setViewability(v);
338 	if (!v)	pd->setDefaultVisibility(FALSE);
339     } else if (GetIntegerAttribute(attr,"hidden",&val)) {
340 	v = (val == 1 ? FALSE : TRUE);
341 	pd->setDefaultVisibility(v);
342     }
343 
344     if (GetIntegerAttribute(attr,"visible",&val)) {
345 	boolean visible=FALSE, viewable=FALSE;
346 	if (val == 0) {
347 	    viewable = TRUE;
348 	    visible = FALSE;
349 	} else if (val == 1) {
350 	    viewable = TRUE;
351 	    visible = TRUE;
352 	} else if (val == 2) {
353 	    viewable = FALSE;
354 	    visible  = FALSE;
355 	}
356 	pd->setViewability(viewable);
357 	pd->setDefaultVisibility(visible);
358     }
359 
360     if (GetIntegerAttribute(attr,"cache",&val))
361 	pd->setDefaultCacheability((Cacheability)val);
362     if (pd->isInput() &&
363 	GetIntegerAttribute(attr,"reroute",&val) &&
364 	(val >= 0))
365 	pd->setRerouteOutput(val+1);	// MDF uses 0 based indices.
366 
367     return TRUE;
368 }
369 
370 /*****************************************************************************/
371 /* _ParseOUTBOARDLine -							     */
372 /*                                                                           */
373 /* Parses and processes the ' OUTBOARD "command" [ ; host ]' line.     */
374 /*                                                                           */
375 /*****************************************************************************/
376 
377 static
_ParseOutboardLine(NodeDefinition * module,char * line,int lineNumber,int start)378 boolean _ParseOutboardLine(NodeDefinition* module,
379 			   char*      line,
380 			   int        lineNumber,
381 			   int        start)
382 {
383     int       current;
384     int       temp;
385     int       i;
386     char*     substring[2];
387 
388     ASSERT(module != NUL(NodeDefinition*));
389     ASSERT(line);
390     ASSERT(lineNumber > 0);
391     ASSERT(start >= 0);
392 
393     current = start;
394 
395     /*
396      * Separate the two sections of the OUTBOARD string.
397      */
398     substring[0] = NULL;
399     substring[1] = NULL;
400     for (i = 0; i < 2; i++)
401     {
402 	/*
403 	 * Skip space.
404 	 */
405 	SkipWhiteSpace(line,current);
406 
407 	/*
408 	 * Tag the beginning of the substring.
409 	 */
410 	substring[i] = &line[current];
411 
412 	/*
413 	 * Find the end of the substring.
414 	 */
415 	while (line[current] != ';' AND line[current] != '\0')
416 	    current++;
417 
418 	/*
419 	 * Mark the end of the substring and remove trailing space.
420 	 */
421 	temp = current - 1;
422 	if (line[current] == ';')
423 	    line[current++] = '\0';
424 	else
425 	    break;
426 
427 	while (line[temp] == ' ' OR line[temp] == '\t')
428 	{
429 	    line[temp] = '\0';
430 	    temp--;
431 	}
432     }
433 
434 #ifdef DEBUG
435     char *s0 = substring[0];
436     char *s1 = substring[1];
437 #endif
438     if (!substring[0])
439     {
440 	goto error;
441     }
442 
443     /*
444      * Parse the first substring:  COMMAND with optional "'s
445      */
446     if (substring[0][0] == '"') {
447 	i = STRLEN(substring[0]);
448 	if (substring[0][i-1] != '"')
449 	    goto error;
450 	substring[0][i-1] = '\0';
451 	i = 1;
452     } else
453 	i = 0;
454 
455     module->setOutboardCommand(&substring[0][i]);
456     if (substring[1])
457         module->setDefaultOutboardHost(substring[1]);
458 
459     return TRUE;
460 
461 error:
462     ErrorMessage("Encountered an erroneous OUTBOARD specification on line %d.",
463 	 lineNumber);
464     return FALSE;
465 }
466 /*****************************************************************************/
467 /* _ParseLOADABLELine -							     */
468 /*                                                                           */
469 /* Parses and processes the ' Loadable file'				     */
470 /*                                                                           */
471 /*****************************************************************************/
472 
473 static
_ParseLoadableLine(NodeDefinition * module,char * line,int lineNumber,int start)474 boolean _ParseLoadableLine(NodeDefinition* module,
475 			   char*      line,
476 			   int        lineNumber,
477 			   int        start)
478 {
479     int       current;
480     int       temp;
481     int       i;
482     char*     substring;
483 
484     ASSERT(module != NUL(NodeDefinition*));
485     ASSERT(line);
486     ASSERT(lineNumber > 0);
487     ASSERT(start >= 0);
488 
489     current = start;
490 
491     /*
492      * Separate the two sections of the LOADABLE string.
493      */
494     substring = NULL;
495     for (i = 0; i < 1; i++)
496     {
497 	/*
498 	 * Skip space.
499 	 */
500 	SkipWhiteSpace(line,current);
501 
502 	/*
503 	 * Tag the beginning of the substring.
504 	 */
505 	substring = &line[current];
506 
507 	/*
508 	 * Find the end of the substring.
509 	 */
510 	while (line[current] != ';' AND line[current] != '\0')
511 	    current++;
512 
513 	/*
514 	 * Mark the end of the substring and remove trailing space.
515 	 */
516 	temp = current - 1;
517 	if (line[current] == ';')
518 	    line[current++] = '\0';
519 	else
520 	    break;
521 
522 	while (line[temp] == ' ' OR line[temp] == '\t')
523 	{
524 	    line[temp] = '\0';
525 	    temp--;
526 	}
527     }
528 
529 #ifdef DEBUG
530     char *s0 = substring;
531 #endif
532     if (!substring)
533     {
534 	goto error;
535     }
536 
537 #ifdef DXD_NON_UNIX_DIR_SEPARATOR
538     for (i=0; i<strlen(substring); i++)
539     	if(substring[i] == '\\') substring[i] = '/';
540 #endif
541 
542     module->setDynamicLoadFile(substring);
543     return TRUE;
544 
545 error:
546     ErrorMessage("Encountered an erroneous LOADABLE specification on line %d.",
547 	 lineNumber);
548     return FALSE;
549 }
550 /*****************************************************************************/
551 /* _ParseInputLine -							     */
552 /*                                                                           */
553 /* Parses and processes the INPUT line.					     */
554 /*                                                                           */
555 /*****************************************************************************/
556 
557 static
_ParseInputLine(Dictionary * mdf,NodeDefinition * module,char * line,int lineNumber,int start)558 boolean _ParseInputLine(Dictionary*    mdf,
559 			   NodeDefinition* module,
560 			   char*      line,
561 			   int        lineNumber,
562 			   int        start)
563 {
564     ParameterDefinition *input = NUL(ParameterDefinition*);
565     Symbol	symbol;
566     int       current;
567     int       temp;
568     int       i;
569     char*     p;
570     char*     substring[4];
571     char *begin_attributes, *end_attributes;
572 
573     ASSERT(mdf != NUL(Dictionary*));
574     ASSERT(module != NUL(NodeDefinition*));
575     ASSERT(line);
576     ASSERT(lineNumber > 0);
577     ASSERT(start >= 0);
578 
579     current = start;
580 
581     /*
582      * Separate the four sections of the INPUT string.
583      */
584     for (i = 0; i < 4; i++)
585     {
586 	/*
587 	 * Skip space.
588 	 */
589 	SkipWhiteSpace(line,current);
590 
591 	/*
592 	 * Tag the beginning of the substring.
593 	 */
594 	substring[i] = &line[current];
595 
596 	/*
597 	 * Find the end of the substring.
598 	 */
599 	while (line[current] != ';' AND line[current] != '\0')
600 	    current++;
601 
602 	/*
603 	 * Mark the end of the substring and remove trailing space.
604 	 */
605 	if (line[current] == ';')
606 	    line[current++] = '\0';
607 	else
608 	    break;
609 
610 	temp = current - 2;
611 	while (line[temp] == ' ' OR line[temp] == '\t')
612 	{
613 	    line[temp] = '\0';
614 	    temp--;
615 	}
616     }
617 
618     if (i < 3)
619     {
620 	ErrorMessage
621 	    ("Encountered an erroneous INPUT specification on line %d.",
622 	     lineNumber);
623 
624 	goto error;
625     }
626 
627     /*
628      * Parse the first substring:  NAME and optional attributes.
629      */
630     begin_attributes = (char *) strchr(substring[0],'[');
631     if (begin_attributes) {
632 	char *p = begin_attributes-1;
633 	// strip trailing white space from name of parameter.
634 	while (IsWhiteSpace(p)) {
635 	    *p = '\0';
636 	    p--;
637   	}
638 	*begin_attributes = '\0';	// Terminate identifier
639 	begin_attributes++;		// Point to beginning of attributes.
640 
641         end_attributes = strrchr(begin_attributes,']');
642 	if (end_attributes)
643 	    *end_attributes = '\0';		// Terminate attributes.
644 	else
645 	    begin_attributes = NULL;
646     }
647     current = 0;
648     if (NOT IsIdentifier(substring[0], current) ||
649 	    (current != STRLEN(substring[0]) &&
650 		!IsWhiteSpace(substring[0], current)))
651     {
652 	ErrorMessage("Invalid %s: %s (file %s, line %d)",
653 	    "input name", substring[0], "MDF", lineNumber);
654 	goto error;
655     }
656 
657     /*
658      * Place the name into the symbol table, and create a parameter with
659      * the given name;
660      */
661     symbol = mdf->getSymbolManager()->registerSymbol(substring[0]);
662     input = new ParameterDefinition(symbol);
663     input->markAsInput();		// Set this as an input parameter
664     input->setDefaultVisibility();	// Default visibility is on.
665 
666     //
667     //  Now that we have a parameter, parse the attributes if there are any.
668     //
669 	if (begin_attributes) {
670 		if (!_ParseParameterAttributes(input,begin_attributes)) {
671 			ErrorMessage("Unrecognized input attribute(s) (%s) in MDF line %d\n",
672 				begin_attributes, lineNumber);
673 			goto error;
674 		}
675     }
676 
677     /*
678      * Parse the second substring:  TYPE.
679      */
680     p = substring[1];
681     if (!ParseMDFTypes(input, p, lineNumber))
682 	goto error;
683 
684     /*
685      * Parse the third substring:  DEFAULT VALUE.
686      */
687 
688     /*
689      * If the value is equal to "(none)", then mark this parameter
690      * as a required parameter.
691      */
692 
693     if (substring[2][0] == '(') {	//  A descriptive value
694 	if (EqualString(substring[2], "(none)"))
695 	    input->setRequired();
696 	else
697 	    input->setNotRequired();
698 	input->setDescriptiveValue(substring[2]);
699     } else if (!input->setDefaultValue(substring[2])) {
700 	    ErrorMessage(
701 		"Default value given on line %d not one of given types.",
702 		 lineNumber);
703 	    goto error;
704     }
705 
706 
707 
708 
709     /*
710      * Parse the fourth substring:  DESCRIPTION.
711      */
712     input->setDescription(substring[3]);
713 
714 
715     /*
716      * One more input parameter processed...
717      */
718     module->addInput(input);
719 
720     return TRUE;
721 
722 error:
723     if (input) delete input;
724     return FALSE;
725 }
726 
727 
728 /*****************************************************************************/
729 /* _ParseOutputLine -						     */
730 /*                                                                           */
731 /* Parses and processes the OUTPUT line.				     */
732 /*                                                                           */
733 /*****************************************************************************/
734 
735 static
_ParseOutputLine(Dictionary * mdf,NodeDefinition * module,char * line,int lineNumber,int start)736 boolean _ParseOutputLine(Dictionary*    mdf,
737 			    NodeDefinition* module,
738 			    char*      line,
739 			    int        lineNumber,
740 			    int        start)
741 {
742     ParameterDefinition* output = NUL(ParameterDefinition*);
743     Symbol	symbol;
744     int       current;
745     int       temp;
746     int       i;
747     char*     p;
748     char*     substring[3];
749 
750     ASSERT(mdf != NUL(Dictionary*));
751     ASSERT(module != NUL(NodeDefinition*));
752     ASSERT(line);
753     ASSERT(lineNumber > 0);
754     ASSERT(start >= 0);
755 
756     current = start;
757 
758     /*
759      * Separate the three sections of the OUTPUT string.
760      */
761     for (i = 0; i < 3; i++)
762     {
763 	/*
764 	 * Skip space.
765 	 */
766 	SkipWhiteSpace(line,current);
767 
768 	/*
769 	 * Tag the beginning of the substring.
770 	 */
771 	substring[i] = &line[current];
772 
773 	/*
774 	 * Find the end of the substring.
775 	 */
776 	while (line[current] != ';' AND line[current] != '\0')
777 	    current++;
778 
779 	/*
780 	 * Mark the end of the substring and remove trailing space.
781 	 */
782 	if (line[current] == ';')
783 	    line[current++] = '\0';
784 	else
785 	    break;
786 
787 	temp = current - 2;
788 	while (line[temp] == ' ' OR line[temp] == '\t')
789 	{
790 	    line[temp] = '\0';
791 	    temp--;
792 	}
793     }
794 
795     if (i < 2)
796     {
797 	ErrorMessage
798 	    ("Encountered an erroneous OUTPUT specification on line %d.",
799 	     lineNumber);
800 
801 	goto error;
802     }
803 
804     /*
805      * Parse the first substring:  NAME.
806      */
807     char *begin_attributes, *end_attributes;
808 #if 0
809     begin_attributes = strchr(substring[0],'[');
810     end_attributes = strrchr(substring[0],']');
811     if (begin_attributes && end_attributes) {
812 	*begin_attributes = '\0';	// Terminate identifier
813 	begin_attributes++;		// Point to beginning of attributes.
814 	*end_attributes = '\0';		// Terminate attributes.
815     }
816 #else
817     begin_attributes = (char *) strchr(substring[0],'[');
818     if (begin_attributes) {
819 	char *p = begin_attributes-1;
820 	// strip trailing white space from name of parameter.
821 	while (IsWhiteSpace(p)) {
822 	    *p = '\0';
823 	    p--;
824   	}
825 	*begin_attributes = '\0';	// Terminate identifier
826 	begin_attributes++;		// Point to beginning of attributes.
827 
828         end_attributes = strrchr(begin_attributes,']');
829 	if (end_attributes)
830 	    *end_attributes = '\0';		// Terminate attributes.
831 	else
832 	    begin_attributes = NULL;
833     }
834 #endif
835     current = 0;
836     if (NOT IsIdentifier(substring[0], current) ||
837 	    (current != STRLEN(substring[0]) &&
838 		!IsWhiteSpace(substring[0], current)))
839     {
840 	ErrorMessage("Invalid %s: %s (file %s, line %d)",
841 	    "output name", substring[0], "MDF", lineNumber);
842 	goto error;
843     }
844 
845     /*
846      * Place the name into the parameter symbol table, and save its index.
847      */
848     symbol = theSymbolManager->registerSymbol(substring[0]);
849     output = new ParameterDefinition(symbol);
850     output->markAsOutput();			// Mark parameter as an output.
851     output->setDefaultVisibility();		// Default visibility is on.
852 
853     //
854     //  Now that we have a parameter, parse the attributes if there are any.
855     //
856     if (begin_attributes) {
857         if (!_ParseParameterAttributes(output,begin_attributes)) {
858 	    ErrorMessage("Unrecognized output attribute(s) (%s) in MDF line %d\n"
859 		, lineNumber);
860 	    goto error;
861 	}
862     }
863 
864     /*
865      * Parse the second substring:  TYPE.
866      */
867     p = substring[1];
868     if (!ParseMDFTypes(output, p, lineNumber))
869 	goto error;
870 
871     /*
872      * Parse the third substring:  DESCRIPTION.
873      */
874     output->setDescription(substring[2]);
875 
876     module->addOutput(output);
877 
878     return TRUE;
879 error:
880     if (output) delete output;
881 
882     return FALSE;
883 }
884 
885 
886 /*****************************************************************************/
887 /* _ParseOptionsLine -						     */
888 /*                                                                           */
889 /* Parses and processes the OPTIONS line.				     */
890 /*                                                                           */
891 /*****************************************************************************/
892 
893 static
_ParseOptionsLine(Dictionary * mdf,NodeDefinition * module,char * line,int lineNumber,int start)894 boolean _ParseOptionsLine(Dictionary*    mdf,
895 			      NodeDefinition* module,
896 			      char*      line,
897 			      int        lineNumber,
898 			      int        start)
899 {
900     ASSERT(mdf != NUL(Dictionary*));
901     ASSERT(module != NUL(NodeDefinition*));
902     ASSERT(line);
903     ASSERT(lineNumber > 0);
904     ASSERT(start >= 0);
905 
906     int inum = module->getInputCount();
907     char *p = &line[start];
908 
909     // assumes we're working on the most recently added param,
910     // which should be an OK assumption.
911     ParameterDefinition* pd = module->getInputDefinition(inum);
912     return ParseMDFOptions (pd, p);
913 }
914 
915 
916 //
917 // Expose OPTIONS line parsing so that it can be called
918 // from MacroDefintion.
919 //
ParseMDFOptions(ParameterDefinition * pd,char * p)920 boolean ParseMDFOptions (ParameterDefinition* pd, char* p)
921 {
922 	/*
923 	* Parse Selection  values (separated by ';').
924 	*/
925 
926 	char *value = new char[STRLEN(p) + 1];
927 	while (*p) {
928 		memset(value, 0, STRLEN(p) + 1);
929 		SkipWhiteSpace(p);
930 		char *from = p, *to = value;
931 		while (*from && (*from != ';')) {
932 			if ((*from == '\\') && (*(from+1) == ';'))
933 				from++;
934 			*to = *from;
935 			from++;
936 			to++;
937 		}
938 		if (to > value) {
939 			if(*from == ';')
940 				*(to--) = '\0';
941 			//
942 			// Clip trailing white space.
943 			//
944 			if(IsWhiteSpace(to))
945 				while ((to > value) && IsWhiteSpace(to))
946 					*(to--) = '\0';
947 			else if(*to)
948 				*(++to) = '\0';
949 		}
950 		pd->addValueOption(value);
951 		if(*from)
952 			p = from+1;
953 		else
954 			p = from;
955 	}
956 
957 	delete[] value;
958 	return TRUE;
959 }
960 
961 
962 /*****************************************************************************/
963 /* _ParseRepeatLine -						     */
964 /*                                                                           */
965 /* Parses and processes the REPEAT line.				     */
966 /*                                                                           */
967 /*****************************************************************************/
968 
969 static
_ParseRepeatLine(Dictionary * mdf,NodeDefinition * module,char * line,int lineNumber,int start,int io_state)970 boolean _ParseRepeatLine(Dictionary*    mdf,
971 			      NodeDefinition* module,
972 			      char*      line,
973 			      int        lineNumber,
974 			      int        start,
975 			      int	io_state)
976 {
977     int current;
978     int temp;
979     int value;
980     int cnt;
981     char *ioname;
982 
983     ASSERT(mdf != NUL(Dictionary*));
984     ASSERT(module != NUL(NodeDefinition*));
985     ASSERT(line);
986     ASSERT(lineNumber > 0);
987     ASSERT(start >= 0);
988     ASSERT(io_state == ST_INPUT || io_state == ST_OUTPUT);
989 
990 
991     current = start;
992 
993     /*
994      * Skip space.
995      */
996     SkipWhiteSpace(line,current);
997 
998     /*
999      * Parse repeat value.
1000      */
1001     temp = current;
1002     if (NOT IsInteger(line, temp))
1003     {
1004 	ErrorMessage
1005 	    ("Encountered error when expecting a repeat value on line %d.",
1006 	     lineNumber);
1007 
1008 	return FALSE;
1009     }
1010 
1011     value = atoi(&line[current]);
1012 
1013     if (io_state == ST_INPUT) {
1014 	cnt = module->getInputCount();
1015         ioname = "input";
1016 	module->setInputRepeatCount(value);
1017     } else {
1018 	cnt = module->getOutputCount();
1019         ioname = "output";
1020 	module->setOutputRepeatCount(value);
1021     }
1022 
1023 
1024     if (value > cnt)
1025     {
1026 	ErrorMessage
1027 	    ("The repeat value on line %d is greater than the number of prior %s parameters.",
1028 	     lineNumber, ioname);
1029 
1030         if (io_state == ST_INPUT)
1031 	    module->setInputRepeatCount(0);
1032 	else
1033 	    module->setOutputRepeatCount(0);
1034 	return FALSE;
1035     }
1036 
1037     return TRUE;
1038 }
1039 
1040 
1041 /*****************************************************************************/
1042 /* _FinishNodeDefinition -						     */
1043 /*                                                                           */
1044 /* Return TRUE if the module was added to the mdf dictionary 		     */
1045 /*                                                                           */
1046 /*                                                                           */
1047 /*****************************************************************************/
1048 
1049 static
_FinishNodeDefinition(Dictionary * mdf,NodeDefinition * module)1050 boolean _FinishNodeDefinition(Dictionary*    mdf,
1051 			   NodeDefinition* module)
1052 {
1053 
1054     ASSERT(mdf != NUL(Dictionary*));
1055     ASSERT(module != NUL(NodeDefinition*));
1056 
1057     Symbol nameSym = module->getNameSymbol();
1058 
1059     //
1060     // Allow, the Get and Set modules to be in the mdf.  They can be placed
1061     // there even if there is not category, which allows us to change to
1062     // using GetLocal/Global and SetLocal/Global instead.
1063     // See GlobalLocalNode.h.
1064     //
1065 
1066     if (module->getCategorySymbol() ||
1067 	(nameSym == NDAllocatorDictionary::GetNodeNameSymbol) ||
1068 	(nameSym == NDAllocatorDictionary::SetNodeNameSymbol)) {
1069 	module->completeDefinition();
1070 	mdf->addDefinition(nameSym,module);
1071 	return TRUE;
1072     } else {
1073 	return FALSE;
1074     }
1075 
1076 }
1077 
1078 
1079 /*****************************************************************************/
1080 /* ReadMDF -								     */
1081 /*                                                                           */
1082 /* Read and parse MDF from open file stream.				     */
1083 /*                                                                           */
1084 /*****************************************************************************/
1085 
ReadMDF(Dictionary * mdf,FILE * input,boolean uionly)1086 boolean ReadMDF(Dictionary* mdf, FILE*   input, boolean uionly)
1087 {
1088 	NodeDefinition *module;
1089 	int        state;
1090 	int        start;
1091 	int        end;
1092 	Symbol	category;
1093 	int        line_number;
1094 	boolean    parsed_flags, checked_flags=FALSE, finished;
1095 	boolean    parsed_category,  parsed_description, parsed_outboard;
1096 	boolean    checked_category=FALSE, checked_description=FALSE, checked_outboard=FALSE;
1097 	boolean	parsed_loadable, checked_loadable=FALSE;
1098 	boolean	checked_repeat=FALSE;
1099 	boolean    get_another_line;
1100 	char*      p;
1101 	char       line[2048];
1102 	int		last_iostate;
1103 
1104 
1105 	ASSERT(mdf != NUL(Dictionary*));
1106 	ASSERT(input);
1107 
1108 	module           = NUL(NodeDefinition*);
1109 	line_number      = 0;
1110 	state            = ST_PACKAGE;
1111 	last_iostate = ST_NONE;
1112 
1113 	finished         = FALSE;
1114 	get_another_line = TRUE;
1115 	parsed_description = parsed_outboard =  parsed_loadable =
1116 		parsed_category = parsed_flags = FALSE;
1117 
1118 	for (;;)
1119 	{
1120 		if (get_another_line)
1121 		{
1122 
1123 			checked_description = parsed_description;
1124 			checked_repeat	= /*parsed_repeat =*/ FALSE;
1125 			checked_loadable	= parsed_loadable;
1126 			checked_outboard	= parsed_outboard;
1127 			checked_category	= parsed_category;
1128 			checked_flags	= parsed_flags;
1129 
1130 			for (;;)
1131 			{
1132 				/*
1133 				* Get a line to parse.
1134 				*/
1135 				p = fgets(line, sizeof(line), input);
1136 				ASSERT(STRLEN(line) < 2048);
1137 				line_number++;
1138 
1139 				/*
1140 				* If no more lines, exit.
1141 				*/
1142 				if (p == NUL(char*))
1143 				{
1144 					finished = TRUE;
1145 					break;
1146 				}
1147 
1148 				/*
1149 				* Skip leading whitespace.
1150 				*/
1151 				for(start = 0;
1152 					line[start] == ' ' OR line[start] == '\t' OR
1153 					line[start] == '\n' OR line[start] == '\r';
1154 				start++)
1155 					;
1156 
1157 				/*
1158 				* If the string is not all spaces and  not a comment exit.
1159 				*/
1160 				if (line[start] != '\0' AND line[start] != '#')
1161 					break;
1162 			}
1163 
1164 			if (NOT finished)
1165 			{
1166 				/*
1167 				* Remove trailing whitespace.
1168 				*/
1169 				for(end = STRLEN(line) - 1;
1170 					line[end] == ' ' OR line[end] == '\t' OR line[end] == '\n' OR line[end] == '\r';
1171 					end--)
1172 					;
1173 
1174 				line[end + 1] = '\0';
1175 			}
1176 		}
1177 		else
1178 		{
1179 			get_another_line = TRUE;
1180 		}
1181 
1182 		/*
1183 		* If no more input, i.e. finished, then exit loop.
1184 		*/
1185 		if (finished)
1186 			break;
1187 
1188 		/*
1189 		* Otherwise, parse according to the current state.
1190 		*/
1191 		switch(state)
1192 		{
1193 		case ST_PACKAGE:
1194 			/*
1195 			* Parse the standalone "PACKAGE" keyword.
1196 			*/
1197 			if (IsToken(line, "PACKAGE", start)) {
1198 				if (!_ParsePackageLine(line,line_number,start)) {
1199 					ErrorMessage
1200 						("Encountered error when parsing \"PACKAGE\" keyword "
1201 						"on line %d.",
1202 						line_number);
1203 					goto error;
1204 				}
1205 				// Continue to try and parse PACKAGE until we move to MODULE
1206 			} else {
1207 				/*
1208 				* Don't get another line yet...
1209 				*/
1210 				get_another_line = FALSE;
1211 				state = ST_MODULE;
1212 			}
1213 
1214 
1215 			break;
1216 
1217 		case ST_MODULE:
1218 			/*
1219 			* Parse "MODULE" keyword.
1220 			*/
1221 			if (NOT IsToken(line, "MODULE", start))
1222 			{
1223 				ErrorMessage
1224 					("Encountered error when expecting \"MODULE\" keyword "
1225 					"on line %d.",
1226 					line_number);
1227 
1228 				goto error;
1229 			}
1230 
1231 			/*
1232 			* If a module definition has already begun, end it here.
1233 			*/
1234 			if (module)
1235 			{
1236 				if (!_FinishNodeDefinition(mdf, module))
1237 					delete module;
1238 			}
1239 
1240 			checked_description = parsed_description = FALSE;
1241 			checked_outboard	= parsed_outboard = FALSE;
1242 			checked_loadable	= parsed_loadable = FALSE;
1243 			checked_category	= parsed_category = FALSE;
1244 			checked_flags	= parsed_flags    = FALSE;
1245 			checked_repeat	= /*parsed_repeat   =*/ FALSE;
1246 
1247 			/*
1248 			* Add the module index to the module index list.
1249 			*/
1250 
1251 			if ( (module = _ParseModuleLine(mdf, line, line_number, start)) )
1252 			{
1253 				/*
1254 				* Next, parse category line.
1255 				*/
1256 				state = ST_CATEGORY;
1257 				if (uionly)
1258 					module->setUILoadedOnly();
1259 			}
1260 			else
1261 			{
1262 				goto error;
1263 			}
1264 			break;
1265 
1266 		case ST_CATEGORY:
1267 			/*
1268 			* Parse "CATEGORY" keyword.
1269 			*/
1270 			checked_category = TRUE;
1271 			if (IsToken(line, "CATEGORY", start))
1272 			{
1273 				/*
1274 				* Skip space.
1275 				*/
1276 				SkipWhiteSpace(line,start);
1277 
1278 				/*
1279 				* Add category name to the category name symbol table and
1280 				* remember the category index.
1281 				*/
1282 				category = theSymbolManager->registerSymbol(&line[start]);
1283 				if (!module) {
1284 					ErrorMessage
1285 						("Encountered unexpected \"CATEGORY\" on line %d.",
1286 						line_number);
1287 					goto error;
1288 				}
1289 
1290 				module->setCategory(category);
1291 				parsed_category = TRUE;
1292 
1293 				if (!parsed_description)
1294 					state = ST_DESCRIPTION;
1295 				else if (!parsed_outboard)
1296 					state = ST_OUTBOARD;
1297 				else if (!parsed_flags)
1298 					state = ST_FLAGS;
1299 				else
1300 					state = ST_INPUT;
1301 			}
1302 			else
1303 			{
1304 				/*
1305 				* No category specified; e.g., mark category field as such.
1306 				*/
1307 				module->setCategory(0);
1308 
1309 				/*
1310 				* Don't get another line yet...
1311 				*/
1312 				get_another_line = FALSE;
1313 				if (!checked_description)
1314 					state = ST_DESCRIPTION;
1315 				else if (!checked_outboard)
1316 					state = ST_OUTBOARD;
1317 				else if (!checked_flags)
1318 					state = ST_FLAGS;
1319 				else
1320 					state = ST_INPUT;
1321 			}
1322 
1323 
1324 			break;
1325 
1326 
1327 		case ST_DESCRIPTION:
1328 
1329 			checked_description = TRUE;
1330 
1331 			/*
1332 			* Parse "DESCRIPTION" keyword.
1333 			*/
1334 			if (IsToken(line, "DESCRIPTION", start))
1335 			{
1336 				/*
1337 				* Skip space.
1338 				*/
1339 				SkipWhiteSpace(line,start);
1340 
1341 				/*
1342 				* Store away the description string.
1343 				*/
1344 				module->setDescription(&line[start]);
1345 				parsed_description = TRUE;
1346 
1347 				if (!parsed_category)
1348 					state = ST_CATEGORY;
1349 				else if (!parsed_outboard)
1350 					state = ST_OUTBOARD;
1351 				else if (!parsed_flags)
1352 					state = ST_FLAGS;
1353 				else
1354 					state = ST_INPUT;
1355 			}
1356 			else
1357 			{
1358 				/*
1359 				* Don't get another line yet...
1360 				*/
1361 				get_another_line = FALSE;
1362 				if (!checked_category)
1363 					state = ST_CATEGORY;
1364 				else if (!checked_outboard)
1365 					state = ST_OUTBOARD;
1366 				else if (!checked_flags)
1367 					state = ST_FLAGS;
1368 				else
1369 					state = ST_INPUT;
1370 			}
1371 
1372 			break;
1373 
1374 		case ST_LOADABLE:
1375 
1376 			checked_loadable = TRUE;
1377 			/*
1378 			* Parse "LOADABLE" keyword.
1379 			*/
1380 			if (IsToken(line, "LOADABLE", start))
1381 			{
1382 				/*
1383 				* Skip space.
1384 				*/
1385 				SkipWhiteSpace(line,start);
1386 
1387 				/*
1388 				* Store away the description string.
1389 				*/
1390 				if (!_ParseLoadableLine(module, line, line_number, start))
1391 					goto error;
1392 				parsed_loadable = TRUE;
1393 
1394 				if (!parsed_category)
1395 					state = ST_CATEGORY;
1396 				else if (!parsed_description)
1397 					state = ST_DESCRIPTION;
1398 				else if (!parsed_flags)
1399 					state = ST_FLAGS;
1400 				else
1401 					state = ST_INPUT;
1402 			}
1403 			else
1404 			{
1405 				/*
1406 				* Don't get another line yet...
1407 				*/
1408 				get_another_line = FALSE;
1409 
1410 				if (!checked_category)
1411 					state = ST_CATEGORY;
1412 				else if (!checked_description)
1413 					state = ST_DESCRIPTION;
1414 				else if (!checked_flags)
1415 					state = ST_FLAGS;
1416 				else if (!checked_outboard)
1417 					state = ST_OUTBOARD;
1418 				else
1419 					state = ST_INPUT;
1420 			}
1421 			break;
1422 
1423 		case ST_OUTBOARD:
1424 
1425 			checked_outboard = TRUE;
1426 			/*
1427 			* Parse "OUTBOARD" keyword.
1428 			*/
1429 			if (IsToken(line, "OUTBOARD", start))
1430 			{
1431 				/*
1432 				* Skip space.
1433 				*/
1434 				SkipWhiteSpace(line,start);
1435 
1436 				/*
1437 				* Store away the description string.
1438 				*/
1439 				if (!_ParseOutboardLine(module, line, line_number, start))
1440 					goto error;
1441 				parsed_outboard = TRUE;
1442 
1443 				if (!parsed_category)
1444 					state = ST_CATEGORY;
1445 				else if (!parsed_description)
1446 					state = ST_DESCRIPTION;
1447 				else if (!parsed_flags)
1448 					state = ST_FLAGS;
1449 				else
1450 					state = ST_INPUT;
1451 			}
1452 			else
1453 			{
1454 				/*
1455 				* Don't get another line yet...
1456 				*/
1457 				get_another_line = FALSE;
1458 
1459 				if (!checked_loadable)
1460 					state = ST_LOADABLE;
1461 				else if (!checked_category)
1462 					state = ST_CATEGORY;
1463 				else if (!checked_description)
1464 					state = ST_DESCRIPTION;
1465 				else if (!checked_flags)
1466 					state = ST_FLAGS;
1467 				else
1468 					state = ST_INPUT;
1469 			}
1470 			break;
1471 
1472 		case ST_FLAGS:
1473 
1474 			checked_flags = TRUE;
1475 			/*
1476 			* Parse "FLAGS" keyword.
1477 			*/
1478 			if (IsToken(line, "FLAGS", start)) {
1479 
1480 				parsed_flags = TRUE;
1481 
1482 				if (strstr(line,"SWITCH")) module->setMDFFlagSWITCH();
1483 				if (strstr(line,"ERR_CONT")) module->setMDFFlagERR_CONT();
1484 				if (strstr(line,"PIN")) module->setMDFFlagPIN();
1485 				if (strstr(line,"SIDE_EFFECT")) module->setMDFFlagSIDE_EFFECT();
1486 				if (strstr(line,"PERSISTENT")) module->setMDFFlagPERSISTENT();
1487 				if (strstr(line,"ASYNC")) module->setMDFFlagASYNCHRONOUS();
1488 				if (strstr(line,"REROUTABLE")) module->setMDFFlagREROUTABLE();
1489 				if (strstr(line,"REACH")) module->setMDFFlagREACH();
1490 				if (strstr(line,"LOOP")) module->setMDFFlagLOOP();
1491 
1492 				if (!parsed_category)
1493 					state = ST_CATEGORY;
1494 				else if (!parsed_description)
1495 					state = ST_DESCRIPTION;
1496 				else if (!parsed_outboard)
1497 					state = ST_OUTBOARD;
1498 				else
1499 					state = ST_INPUT;
1500 			}
1501 			else
1502 			{
1503 				/*
1504 				* Don't get another line yet...
1505 				*/
1506 				get_another_line = FALSE;
1507 
1508 				if (!checked_category)
1509 					state = ST_CATEGORY;
1510 				else if (!checked_description)
1511 					state = ST_DESCRIPTION;
1512 				else if (!checked_outboard)
1513 					state = ST_OUTBOARD;
1514 				else
1515 					state = ST_INPUT;
1516 			}
1517 			break;
1518 
1519 		case ST_INPUT:
1520 			last_iostate = ST_INPUT;
1521 			if (IsToken(line, "INPUT", start))
1522 			{
1523 				if (_ParseInputLine(mdf, module, line, line_number, start))
1524 				{
1525 					/*
1526 					* Continue to parse input line.
1527 					*/
1528 					state = ST_INPUT;
1529 				}
1530 				else
1531 				{
1532 					goto error;
1533 				}
1534 			}
1535 			else
1536 			{
1537 				/*
1538 				* Don't get another line yet...
1539 				*/
1540 				get_another_line = FALSE;
1541 
1542 				/*
1543 				* If not successful, try parsing repeat line.
1544 				*/
1545 				if (checked_repeat)
1546 					state = ST_OUTPUT;
1547 				else
1548 					state = ST_OPTIONS;
1549 
1550 			}
1551 			break;
1552 
1553 
1554 		case ST_OUTPUT:
1555 			last_iostate = ST_OUTPUT;
1556 			if (IsToken(line, "OUTPUT", start))
1557 			{
1558 				if (_ParseOutputLine(mdf, module, line, line_number, start))
1559 				{
1560 					/*
1561 					* Continue to parse output line.
1562 					*/
1563 					state = ST_OUTPUT;
1564 				}
1565 				else
1566 				{
1567 					goto error;
1568 				}
1569 			}
1570 			else
1571 			{
1572 				/*
1573 				* Don't get another line yet...
1574 				*/
1575 				get_another_line = FALSE;
1576 
1577 				/*
1578 				* If not successful, assume end of module definition...
1579 				*/
1580 				state = ST_REPEAT;
1581 			}
1582 			break;
1583 
1584 		case ST_REPEAT:
1585 			checked_repeat = TRUE;
1586 			if (IsToken(line, "REPEAT", start))
1587 			{
1588 				if (_ParseRepeatLine(mdf, module, line, line_number,
1589 					start, last_iostate))
1590 				{
1591 					/*
1592 					* Next, parse output or module line.
1593 					*/
1594 					if (last_iostate == ST_INPUT)  {
1595 						state = ST_OUTPUT;
1596 					} else if (last_iostate == ST_OUTPUT)  {
1597 						state = ST_PACKAGE;
1598 					} else
1599 						ASSERT(0);
1600 					/*parsed_repeat = TRUE;*/
1601 					get_another_line = TRUE;
1602 				}
1603 				else
1604 				{
1605 					goto error;
1606 				}
1607 			}
1608 			else
1609 			{
1610 				/*
1611 				* Don't get another line yet...
1612 				*/
1613 				get_another_line = FALSE;
1614 
1615 				/*
1616 				* If not successful, try parsing output or module line.
1617 				*/
1618 				if (last_iostate == ST_INPUT) {
1619 					state = ST_INPUT;
1620 				} else if (last_iostate == ST_OUTPUT) {
1621 					state = ST_PACKAGE;
1622 				} else
1623 					ASSERT(0);
1624 			}
1625 			break;
1626 
1627 		case ST_OPTIONS:
1628 			ASSERT(last_iostate == ST_INPUT);
1629 			if (IsToken(line, "OPTIONS", start))
1630 			{
1631 				if (_ParseOptionsLine(mdf, module, line, line_number, start))
1632 				{
1633 					/*
1634 					* Next, parse another line of selections
1635 					*/
1636 					state = ST_OPTIONS;
1637 					get_another_line = TRUE;
1638 				}
1639 				else
1640 				{
1641 					goto error;
1642 				}
1643 			}
1644 			else
1645 			{
1646 				/*
1647 				* Don't get another line yet...
1648 				*/
1649 				get_another_line = FALSE;
1650 
1651 				/*
1652 				* If not successful, try parsing output or module line.
1653 				*/
1654 				if (!checked_repeat)
1655 					state = ST_REPEAT;
1656 				else
1657 					state = ST_INPUT;
1658 			}
1659 			break;
1660 
1661 
1662 		default:
1663 			ASSERT(FALSE);
1664 		}
1665 	}
1666 
1667 	/*
1668 	* Finish the module definition.
1669 	*/
1670 	if (module)
1671 	{
1672 		if (!_FinishNodeDefinition(mdf, module))
1673 			delete module;
1674 	}
1675 
1676 	return TRUE;
1677 
1678 error:
1679 	if (module) delete module;
1680 
1681 	return FALSE;
1682 }
1683 
LoadMDFFile(const char * file,const char * mdftype,Dictionary * mdf,boolean uionly)1684 boolean LoadMDFFile(const char *file, const char *mdftype, Dictionary *mdf,
1685 					boolean uionly)
1686 {
1687 	FILE *input;
1688 	boolean parsed;
1689 
1690 	if (!file || !*file)
1691 		return TRUE;
1692 
1693 	input = fopen(file, "r");
1694 	if (input != NUL(FILE*))
1695 	{
1696 		parsed = ReadMDF(mdf, input, uionly);
1697 		fclose(input);
1698 
1699 		if (NOT parsed)
1700 		{
1701 			ErrorMessage("Error found in %s module definition file \"%s\".",
1702 				mdftype,file);
1703 			return FALSE;
1704 		}
1705 	}
1706 	else
1707 	{
1708 		ErrorMessage ("Cannot open %s module description file \"%s\".",
1709 			mdftype,file);
1710 		return FALSE;
1711 	}
1712 	return TRUE;
1713 }
1714 
1715 #ifdef NOT_YET
ReadMDFFiles(const char * root,Dictionary * mdf)1716 boolean ReadMDFFiles(const char *root, Dictionary *mdf)
1717 {
1718 
1719     FILE*   input;
1720     boolean parsed;
1721     char    pathname[256];
1722 
1723 
1724     /*
1725      * Load system module description file.
1726      */
1727     sprintf(pathname, "%s/lib/dx.mdf", root);
1728 
1729     if (!LoadMDFFile(pathname,"system",mdf))
1730 	return FALSE;
1731 
1732     /*
1733      * Load UI module description file.
1734      */
1735     sprintf(pathname, "%s/ui/ui.mdf", root);
1736 
1737     if (!LoadMDFFile(pathname,"UI",mdf))
1738 	return FALSE;
1739 
1740     /*
1741      * Load user module description file, if defined.
1742      */
1743     if (program->user_module)
1744     {
1745 	input = fopen(program->user_module, "r");
1746 	if (input != NUL(FILE*))
1747 	{
1748 	    parsed = ReadMDF(program->mdf, input);
1749 	    fclose(input);
1750 
1751 	    if (NOT parsed)
1752 	    {
1753 		ErrorMessage
1754 		    ("Error found in user module definition file \"%s\".",
1755 		     program->user_module);
1756 		return FALSE;
1757 	    }
1758 	}
1759 	else
1760 	{
1761 	    ErrorMessage
1762 		("Cannot open user module description file \"%s\".",
1763 		 program->user_module);
1764 	    return FALSE;
1765 	}
1766     }
1767 
1768     /*
1769      * Need to initialize MDF after all the module description files have
1770      * been parsed, and all the macro definitions have been added.
1771      */
1772     InitializeMDF(program->mdf);
1773 
1774     /*
1775      * Install the macros.
1776      */
1777     if (program->macros)
1778     {
1779 	uipInstallMacros(program);
1780     }
1781 
1782     /*
1783      * Return successfully.
1784      */
1785     return TRUE;
1786 }
1787 #endif // NOT_YET
1788 
1789 #ifdef NOT_YET
1790 /*****************************************************************************/
1791 /* _CompareModules -							     */
1792 /*                                                                           */
1793 /* Compares two module name strings.					     */
1794 /*                                                                           */
1795 /*****************************************************************************/
1796 
1797 static
_CompareModules(int * first,int * second)1798 int _CompareModules(int* first,
1799 		       int* second)
1800 {
1801     ASSERT(first);
1802     ASSERT(second);
1803 
1804     return
1805 	uiuStrcmp(_mdf->module[*first].function, _mdf->module[*second].function);
1806 }
1807 
1808 
1809 /*****************************************************************************/
1810 /* SortMDF -								     */
1811 /*                                                                           */
1812 /* Sorts an MDF list by name.                                                */
1813 /*                                                                           */
1814 /*****************************************************************************/
1815 
SortMDF(Dictionary * mdf)1816 void SortMDF(Dictionary* mdf)
1817 {
1818     ASSERT(mdf != NUL(Dictionary*));
1819 
1820     /*
1821      * Sort the module list in alphabetical order.
1822      */
1823     _mdf = mdf;
1824     qsort(mdf->module_index, mdf->n_modules, sizeof(int), _CompareModules);
1825 }
1826 
1827 
1828 
1829 /*****************************************************************************/
1830 /* InitializeMDF -							     */
1831 /*                                                                           */
1832 /* Initializes an MDF after all the various module description files have    */
1833 /* been read and parsed.						     */
1834 /*                                                                           */
1835 /*****************************************************************************/
1836 
InitializeMDF(UimMDF * mdf)1837 void InitializeMDF(UimMDF* mdf)
1838 {
1839     UimModule* module;
1840     int        i;
1841     int        k;
1842 
1843     ASSERT(mdf);
1844 
1845     /*
1846      * Sort the module list in alphabetical order.
1847      */
1848     _mdf = mdf;
1849     qsort(mdf->module_index, mdf->n_modules, sizeof(int), _CompareModules);
1850 
1851     /*
1852      * Save special UI module names and categories (indices).
1853      */
1854     uiuStringTableFind(mdf->name_table, "Integer",     &mdf->name.integer);
1855     uiuStringTableFind(mdf->name_table, "Scalar",      &mdf->name.scalar);
1856     uiuStringTableFind(mdf->name_table, "Vector",      &mdf->name.vector);
1857     uiuStringTableFind(mdf->name_table, "Value",       &mdf->name.value);
1858     uiuStringTableFind(mdf->name_table, "String",      &mdf->name.string);
1859     uiuStringTableFind(mdf->name_table, "Selector",    &mdf->name.selector);
1860     uiuStringTableFind(mdf->name_table, "IntegerList", &mdf->name.integer_list);
1861     uiuStringTableFind(mdf->name_table, "ScalarList",  &mdf->name.scalar_list);
1862     uiuStringTableFind(mdf->name_table, "VectorList",  &mdf->name.vector_list);
1863     uiuStringTableFind(mdf->name_table, "ValueList",   &mdf->name.value_list);
1864     uiuStringTableFind(mdf->name_table, "StringList",  &mdf->name.string_list);
1865 
1866     uiuStringTableFind
1867 	(mdf->category_table, "Interactor", &mdf->name.interactors);
1868 
1869     uiuStringTableFind(mdf->name_table, "Colormap",    &mdf->name.colormap);
1870     uiuStringTableFind(mdf->name_table, "Image",       &mdf->name.image);
1871     uiuStringTableFind(mdf->name_table, "Input",       &mdf->name.input);
1872     uiuStringTableFind(mdf->name_table, "Output",      &mdf->name.output);
1873     uiuStringTableFind(mdf->name_table, "Receiver",    &mdf->name.receiver);
1874     uiuStringTableFind(mdf->name_table, "Sequencer",   &mdf->name.sequencer);
1875     uiuStringTableFind(mdf->name_table, "Transmitter", &mdf->name.transmitter);
1876     uiuStringTableFind(mdf->name_table, "VCR",         &mdf->name.vcr);
1877 
1878     uiuStringTableFind(mdf->name_table, "Display",     &mdf->name.display);
1879     uiuStringTableFind(mdf->name_table, "ProbeList",   &mdf->name.probe_list);
1880     uiuStringTableFind(mdf->name_table, "Probe",       &mdf->name.probe);
1881 
1882 #ifdef EPIC
1883     uiuStringTableFind(mdf->name_table, "Epic", &mdf->name.epic);
1884 #else
1885     mdf->name.epic = -1;
1886 #endif
1887 
1888 #ifdef CAD
1889     uiuStringTableFind(mdf->name_table, "Navigate", &mdf->name.navigate);
1890 #else
1891     mdf->name.navigate = -1;
1892 #endif
1893 
1894     /*
1895      * Adjust certain parameters of various modules to be invisible.
1896      */
1897     FOR_EACH_MODULE(module, i, mdf)
1898     {
1899 	if (module->dialog_type == CONF_DIALOG_COMPUTE)
1900 	{
1901 	    module->input[0].visible = FALSE;
1902 	}
1903 	else if (module->name == mdf->name.colormap)
1904 	{
1905 	    module->input[0].visible = FALSE;
1906 	    module->input[1].visible = FALSE;
1907 	    module->input[2].visible = FALSE;
1908 	    module->input[3].visible = FALSE;
1909 	}
1910 	else if (module->name == mdf->name.image)
1911 	{
1912 	    /*
1913 	     * Make every parameter, except the second one, invisible.
1914 	     */
1915 	    for (k = 0; k < module->n_inputs; k++)
1916 	    {
1917 		if (k != 1)
1918 		{
1919 		    module->input[k].visible = FALSE;
1920 		}
1921 	    }
1922 	}
1923 	else if (module->name == mdf->name.navigate)
1924 	{
1925 	    /*
1926 	     * Make most parameters invisible.
1927 	     */
1928 	    for (k = 0; k < module->n_inputs; k++)
1929 	    {
1930 		if (k != 1 AND k != 29 AND k != 30)
1931 		{
1932 		    module->input[k].visible = FALSE;
1933 		}
1934 	    }
1935 	}
1936     }
1937 }
1938 #endif // NOT_YET
1939 
1940 #ifdef COMMENT
1941 
1942 /*****************************************************************************/
1943 /* _uimPrintMDF -							     */
1944 /*                                                                           */
1945 /* Prints binary form of module descriptions in ASCII.  prints only one      */
1946 /* module name, if supplied; otherwise prints the entire table of modules.   */
1947 /*                                                                           */
1948 /*****************************************************************************/
1949 
1950 static
_uimPrintMDF(UimMDF * mdf,FILE * output)1951 void _uimPrintMDF(UimMDF* mdf,
1952 		  FILE*   output)
1953 {
1954     UimModule* module;
1955     UimParam*  parameter;
1956     int	       i;
1957     int        j;
1958     int        k;
1959 
1960     ASSERT(mdf);
1961     ASSERT(output);
1962 
1963     FOR_EACH_MODULE(module, i, mdf)
1964     {
1965 	fprintf(output,	"MODULE %s\n",module->function);
1966 
1967 	fprintf(output,
1968 		"CATEGORY %s\n",
1969 	        uiuStringTableGet(mdf->category_table, module->category));
1970 
1971 	if (module->description)
1972 	{
1973 	    fprintf(output, "DESCRIPTION %s\n", module->description);
1974 	}
1975 
1976 	FOR_EACH_MODULE_INPUT(parameter, j, module)
1977 	{
1978 	    fprintf(output,
1979 		    "INPUT %s; ",
1980 		    uiuStringTableGet(mdf->label_table, parameter->label));
1981 
1982 	    for (k = 0; k < parameter->type_count; k++)
1983 	    {
1984 		fputs(uimTypeToString(module->type[parameter->type + k]),
1985 		      output);
1986 
1987 		if (k < parameter->type_count - 1)
1988 		{
1989 		    fputs(" or ", output);
1990 		}
1991 	    }
1992 
1993 	    if (parameter->default_value)
1994 	    {
1995 		fprintf(output, "; %s", parameter->default_value);
1996 	    }
1997 
1998 	    if (parameter->description)
1999 	    {
2000 		fprintf(output, "; %s", parameter->description);
2001 	    }
2002 
2003 	    fputc('\n', output);
2004 	}
2005 
2006 	if (module->n_repeats)
2007 	{
2008 	    fprintf(output, "REPEAT %d\n", module->n_repeats);
2009 	}
2010 
2011 	FOR_EACH_MODULE_OUTPUT(parameter, j, module)
2012 	{
2013 	    fprintf(output,
2014 		    "OUTPUT %s; ",
2015 		    uiuStringTableGet(mdf->label_table, parameter->label));
2016 
2017 	    for (k = 0; k < parameter->type_count; k++)
2018 	    {
2019 		fputs(uimTypeToString(module->type[parameter->type + k]),
2020 		      output);
2021 
2022 		if (k < parameter->type_count - 1)
2023 		{
2024 		    fputs(" or ", output);
2025 		}
2026 	    }
2027 
2028 	    if (parameter->description)
2029 	    {
2030 		fprintf(output, "; %s", parameter->description);
2031 	    }
2032 
2033 	    fputc('\n', output);
2034 	}
2035 
2036 	fputc('\n', output);
2037     }
2038 }
2039 
2040 #endif
2041