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 
11 
12 #include <dx/dx.h>
13 #include "config.h"
14 #include "pmodflags.h"
15 #include "d.h"
16 #include "_macro.h"
17 #include "_variable.h"
18 #include "attribute.h"
19 #include "graph.h"
20 #include "parse.h"
21 #include "path.h"
22 #include "utils.h"
23 #include "log.h"
24 #include "graphIntr.h"
25 
26 #define	MACRO_DEPTH	512
27 #define	MACRO_QUIT	MACRO_DEPTH
28 
29 /*
30  * These can be statics since graph construction takes place on a single
31  * processor.
32  *
33  * $$$$$ If we need to save some space we can dynamically allocate
34  * $$$$$ cells to hold the names etc. but at a performance penalty.
35  */
36 
37 static char	*_macro_stack[MACRO_DEPTH];
38 static int	_macro_depth = 0;
39 
40 static int	_nocache_depth = 0;
41 static int	_nocache_stack[MACRO_DEPTH];
42 
43 int
_dxf_ExNoCachePush(int n)44 _dxf_ExNoCachePush (int n)
45 {
46     int		nc	= FALSE;
47 
48     if (_nocache_depth > 0)
49     {
50 	if (_nocache_depth < MACRO_DEPTH)
51 	    nc = _nocache_stack[_nocache_depth - 1];
52 	else
53 	    nc = _nocache_stack[MACRO_DEPTH - 1];
54     }
55 
56     nc = nc || n;
57 
58     if (_nocache_depth < MACRO_DEPTH)
59 	_nocache_stack[_nocache_depth++] = nc;
60     else
61 	_nocache_depth++;
62 
63     return (nc);
64 }
65 
66 
67 void
_dxf_ExNoCachePop()68 _dxf_ExNoCachePop ()
69 {
70     if (--_nocache_depth < 0)
71 	_nocache_depth = 0;
72 }
73 
74 /*
75  * Determines whether a recursive macro call has been made.  If so
76  * generates an error message, if not pushes the macro name onto the
77  * stack.
78  */
79 
80 #define	ADVANCE(_bp)	while (*(_bp)) (_bp)++
81 #define	ADDARROW(_bp)	{strcpy (_bp, " -> "); ADVANCE (_bp);}
82 
_dxf_ExMacroRecursionCheck(char * name,_ntype type)83 int _dxf_ExMacroRecursionCheck (char *name, _ntype type)
84 {
85     int		i;
86     int		j;
87     char	*warning = "Macro recursion:  ";
88     char	*message;
89     char	*mptr;
90     int		len;
91     int		d;
92 
93     if (type != NT_MACRO)
94 	return (FALSE);
95 
96     d = _macro_depth < MACRO_DEPTH ? _macro_depth : MACRO_DEPTH;
97 
98     for (i = 0; i < d; i++)
99     {
100 	if (name == _macro_stack[i] && ! strcmp (name, _macro_stack[i]))
101 	{
102 	    /* Figure out how much space we need for the message */
103 	    for (j = 0, len = 0; j < d; j++)
104 		len += strlen (_macro_stack[j]);
105 
106 	    len += strlen (warning);	/* for inital message		*/
107 	    len += 4 * _macro_depth;	/* for ' -> '			*/
108 	    len += strlen (name);	/* for bad guy			*/
109 	    len++;			/* for '\000'			*/
110 
111 	    if ((mptr = message = DXAllocate (len)) == NULL)
112 		DXUIMessage ("ERROR", "%s%s", warning, name);
113 	    else
114 	    {
115 		strcpy (mptr, warning);
116 		ADVANCE (mptr);
117 
118 		for (j = 0; j < d; j++)
119 		{
120 		    strcpy (mptr, _macro_stack[j]);
121 		    ADVANCE (mptr);
122 		    ADDARROW (mptr);
123 		}
124 
125 		strcpy (mptr, name);
126 		ADVANCE (mptr);
127 		*mptr = '\000';
128 
129 		DXUIMessage ("ERROR", message);
130 		DXFree ((Pointer) message);
131 	    }
132 
133 	    return (TRUE);
134 	}
135     }
136 
137     if (_macro_depth >= MACRO_QUIT)
138     {
139 	DXUIMessage ("ERROR", "Macro depth = %d, assuming macro recursion", _macro_depth);
140 	return (TRUE);
141     }
142 
143     if (_macro_depth < MACRO_DEPTH)
144 	_macro_stack[_macro_depth++] = name;
145     else
146 	_macro_depth++;
147 
148     return (FALSE);
149 }
150 
151 /*
152  * Clears the macro recursion checking structure.  Shouldn't be
153  * necessary but just in case something left us in a funky state.
154  */
155 
_dxf_ExMacroRecursionInit()156 void _dxf_ExMacroRecursionInit ()
157 {
158     _macro_depth = 0;
159     _nocache_depth = 0;
160 }
161 
162 /*
163  * Pops one level of macro call from the recursion check.
164  */
165 
_dxf_ExMacroRecursionPop(char * name,_ntype type)166 void _dxf_ExMacroRecursionPop (char *name, _ntype type)
167 {
168     if (type != NT_MACRO)
169 	return;
170 
171     if (--_macro_depth < 0)
172 	_macro_depth = 0;
173 }
174 
175 
176 
177 
_dxf_ExPrintNode(node * n)178 void _dxf_ExPrintNode(node*n)
179 {
180     node *sn;
181 
182     if (n == NULL)
183     {
184 	DXMessage("NULL");
185 	return;
186     }
187     switch(n->type) {
188     case NT_MACRO:
189 	DXMessage("macro");
190 	_dxf_ExPrintNode(n->v.macro.id);
191 	DXMessage("\t(");
192 	for (sn = n->v.macro.in; sn; sn = sn->next)
193 	    _dxf_ExPrintNode(sn);
194 	DXMessage("\t) -> (");
195 	for (sn = n->v.macro.out; sn; sn = sn->next)
196 	    _dxf_ExPrintNode(sn);
197 	DXMessage("\t)");
198 	DXMessage("{");
199 	for (sn = n->v.macro.def.stmt; sn; sn = sn->next)
200 	{
201 	    _dxf_ExPrintNode(sn);
202 	    DXMessage(";");
203 	}
204 	DXMessage("}");
205 	break;
206 
207     case NT_MODULE:
208 	for (sn = n->v.module.out; sn; sn = sn->next)
209 	    _dxf_ExPrintNode(sn);
210 	DXMessage("=");
211 	_dxf_ExPrintNode(n->v.module.id);
212 	DXMessage("(");
213 	for (sn = n->v.module.in; sn; sn = sn->next)
214 	    _dxf_ExPrintNode(sn);
215 	DXMessage(")");
216 	break;
217 
218     case NT_ASSIGNMENT:
219 	for (sn = n->v.assign.lval; sn; sn = sn->next)
220 	    _dxf_ExPrintNode(sn);
221 	DXMessage("=");
222 	for (sn = n->v.assign.rval; sn; sn = sn->next)
223 	    _dxf_ExPrintNode(sn);
224 	break;
225 
226     case NT_PRINT:
227 	DXMessage("NT_PRINT");
228 	break;
229 
230     case NT_ATTRIBUTE:
231 	DXMessage("NT_ATTRIBUTE");
232 	break;
233 
234     case NT_CALL:
235 	_dxf_ExPrintNode(n->v.call.id);
236 	DXMessage("(");
237 	for (sn = n->v.call.arg; sn; sn = sn->next)
238 	    _dxf_ExPrintNode(sn);
239 	DXMessage(")");
240 	break;
241 
242     case NT_ARGUMENT:
243 	_dxf_ExPrintNode(n->v.arg.val);
244 	break;
245 
246     case NT_LOGICAL:
247 	DXMessage("NT_LOGICAL");
248 	break;
249 
250     case NT_ARITHMETIC:
251 	DXMessage("NT_ARITHMETIC");
252 	break;
253 
254     case NT_CONSTANT:
255 	DXMessage("NT_CONSTANT");
256 	break;
257 
258     case NT_ID:
259 	if (n->v.id.dflt != NULL)
260 	{
261 	    DXMessage("%s = ", n->v.id.id);
262 	    _dxf_ExPrintNode(n->v.id.dflt);
263 	}
264 	else
265 	{
266 	    DXMessage("%s", n->v.id.id);
267 	}
268 	break;
269 
270     case NT_EXID:
271 	DXMessage("NT_EXID");
272 	break;
273 
274     case NT_BACKGROUND:
275 	DXMessage("NT_BACKGROUND");
276 	break;
277 
278     case NT_PACKET:
279 	DXMessage("NT_PACKET");
280 	break;
281 
282     case NT_DATA:
283 	DXMessage("NT_DATA");
284 	break;
285 
286     default:
287 	DXMessage("Unknown type %d", n->type);
288 	break;
289     }
290 }
291