1 /*
2  *   Copyright (C) 1988-1991 Yale University
3  *
4  *   This work is distributed in the hope that it will be useful; you can
5  *   redistribute it and/or modify it under the terms of the
6  *   GNU General Public License as published by the Free Software Foundation;
7  *   either version 2 of the License,
8  *   or any later version, on the following conditions:
9  *
10  *   (a) YALE MAKES NO, AND EXPRESSLY DISCLAIMS
11  *   ALL, REPRESENTATIONS OR WARRANTIES THAT THE MANUFACTURE, USE, PRACTICE,
12  *   SALE OR
13  *   OTHER DISPOSAL OF THE SOFTWARE DOES NOT OR WILL NOT INFRINGE UPON ANY
14  *   PATENT OR
15  *   OTHER RIGHTS NOT VESTED IN YALE.
16  *
17  *   (b) YALE MAKES NO, AND EXPRESSLY DISCLAIMS ALL, REPRESENTATIONS AND
18  *   WARRANTIES
19  *   WHATSOEVER WITH RESPECT TO THE SOFTWARE, EITHER EXPRESS OR IMPLIED,
20  *   INCLUDING,
21  *   BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
22  *   PARTICULAR
23  *   PURPOSE.
24  *
25  *   (c) LICENSEE SHALL MAKE NO STATEMENTS, REPRESENTATION OR WARRANTIES
26  *   WHATSOEVER TO
27  *   ANY THIRD PARTIES THAT ARE INCONSISTENT WITH THE DISCLAIMERS BY YALE IN
28  *   ARTICLE
29  *   (a) AND (b) above.
30  *
31  *   (d) IN NO EVENT SHALL YALE, OR ITS TRUSTEES, DIRECTORS, OFFICERS,
32  *   EMPLOYEES AND
33  *   AFFILIATES BE LIABLE FOR DAMAGES OF ANY KIND, INCLUDING ECONOMIC DAMAGE OR
34  *   INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER YALE SHALL BE
35  *   ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE
36  *   POSSIBILITY OF THE FOREGOING.
37  *
38  */
39 
40 /* -----------------------------------------------------------------
41 FILE:	    plot.c
42 DESCRIPTION:Plot routines for Cricket Graph.
43 CONTENTS:
44 DATE:	    Feb 13, 1988 REVISIONS:  Jan 29, 1989 - changed msg to YmsgG.
45 	    Feb 01, 1989 - move all graphic routines to graphics.c
46 	    Mar 30, 1989 - changed tile datastructure.
47 	    Apr 29, 1990 - added message.h
48 	    Fri Jan 18 18:38:36 PST 1991 - fixed to run on AIX.
49 ----------------------------------------------------------------- */
50 
51 #include <stdarg.h>
52 #include <string.h>
53 #include <yalecad/base.h>
54 #include <yalecad/debug.h>
55 #include <yalecad/message.h>
56 #include <yalecad/file.h>
57 #include <yalecad/string.h>
58 
59 #define MAXARGS 20
60 typedef struct {
61     char  fileName[LRECL] ;
62     FILE  *fp ;
63     BOOL  headPrintedAlready ;
64     BOOL  graphFlushed ;
65 } YPLOTTYPE, *YPLOTPTR ;
66 
67 static YPLOTTYPE gfileS[MAXARGS] ;
68 static INT gfilenoS = 0 ;
69 static BOOL graphFilesS = TRUE ;
70 
71 
72 static INT findType();
73 
Yplot_control(toggle)74 void Yplot_control( toggle )
75 BOOL toggle ;
76 {
77     graphFilesS = toggle ;
78 } /* end YgraphControl */
79 
80 /* graph init uses variable number of arguments */
Yplot_init(int dval,...)81 void Yplot_init( int dval, ... )
82 {
83 
84     va_list ap ;
85     char *graphName;
86     YPLOTPTR gptr ;
87 
88     va_start(ap, dval) ;
89 
90     if( !(graphFilesS) ){
91 	/* don't do anything if flag is not set */
92 	va_end(ap) ;
93 	return ;
94     }
95 
96     while( graphName = va_arg( ap, char * ) ){
97 	/* save graph file name */
98 	gptr = &(gfileS[gfilenoS++]) ;
99 	sprintf( gptr->fileName,"%s",graphName ) ;
100 	gptr->fp = TWOPEN( graphName, "w", ABORT ) ;
101 	gptr->headPrintedAlready = FALSE ;
102 	gptr->graphFlushed = TRUE ;
103     }
104     va_end(ap) ;
105 }
106 
107 /* graph init uses variable number of arguments */
Yplot_heading(int dval,...)108 void Yplot_heading( int dval, ... )
109 {
110 
111     va_list ap ;
112     char *gName, *varName ;
113     YPLOTPTR gptr ;
114     INT i ;
115     FILE *fp ;
116 
117     va_start(ap, dval) ;
118 
119     if( !(graphFilesS) ){
120 	/* don't do anything if flag is not set */
121 	va_end(ap) ;
122 	return ;
123     }
124 
125     /* first argument is always graph file name */
126     if( !(gName = va_arg( ap, char * ) )){
127 	M(ERRMSG,"GRAPH","problem with first argument\n" ) ;
128 	va_end(ap) ;
129 	return ;
130     } else {
131 	/* find matching file */
132 	for( i=0;i<gfilenoS;i++ ){
133 	    if( strcmp( gName, gfileS[i].fileName ) == STRINGEQ ){
134 		if( gfileS[i].headPrintedAlready ){
135 		    return ;
136 		}
137 		fp = gfileS[i].fp ;
138 		fprintf( fp, "*\n" ) ;
139 		break ;
140 	    }
141 	}
142 	if( i >= gfilenoS ){
143 	    sprintf( YmsgG,
144 		"couldn't find file %s name in opened file list\n" ) ;
145 	    M(ERRMSG,"GRAPH", YmsgG ) ;
146 	    return ;
147 	}
148     }
149     gfileS[i].headPrintedAlready = TRUE ;
150     while( varName = va_arg( ap, char * ) ){
151 	fprintf( fp, "%s\t", varName ) ;
152     }
153     fprintf( fp, "\n" ) ;
154     va_end(ap) ;
155 }
156 
Yplot_close()157 void Yplot_close()
158 {
159     INT i ;
160 
161     if( !(graphFilesS) ){
162 	/* don't do anything if flag is not set */
163 	return ;
164     }
165 
166     for( i = 0; i<gfilenoS;i++ ){
167 	TWCLOSE( gfileS[i].fp ) ;
168     }
169 }
170 
171 #define NULL_TYPE 0
172 #define INT_TYPE  1
173 #define CHAR_TYPE 2
174 #define STRG_TYPE 3
175 #define DOUB_TYPE 4
176 
177 /* This is what argument list looks like - use it to pass any type */
178 /* of variable to graph */
179 /* GRAPH( graphFileName, xVarformat, xVar, yVarformat, yVars... ) */
Yplot(int dval,...)180 void Yplot( int dval, ... )
181 {
182     va_list ap ;
183     char *gName ;
184     char *control ;
185     char *format ;
186     char gchar ;
187     char *gstr ;
188     char **tokenBuf ;
189     INT gint ;
190     INT i , type, numtokens ;
191     DOUBLE gdoub ;
192     FILE *fp ;
193     static char copyformatS[LRECL] ;
194     /* static INT findType();*/
195 
196     va_start(ap, dval) ;
197     if( !(graphFilesS) ){
198 	/* don't do anything if flag is not set */
199 	va_end(ap) ;
200 	return ;
201     }
202 
203     /* first argument is always graph file name */
204     if( !(gName = va_arg( ap, char * ) )){
205 	M(ERRMSG,"GRAPH","problem with first argument\n" ) ;
206 	va_end(ap) ;
207 	return ;
208     } else {
209 	/* find matching file */
210 	for( i=0;i<gfilenoS;i++ ){
211 	    if( strcmp( gName, gfileS[i].fileName ) == STRINGEQ ){
212 		fp = gfileS[i].fp ;
213 		break ;
214 	    }
215 	}
216 	if( i >= gfilenoS ){
217 	    sprintf( YmsgG,
218 		"couldn't find file %s name in opened file list\n" ) ;
219 	    M(ERRMSG,"GRAPH", YmsgG ) ;
220 	    return ;
221 	}
222     }
223 
224     /* GRAPH( graphFileName, xVarformat, xVar, yVarformat, yVars... ) */
225     /* second argument is control for xvariable */
226     if( !(control = va_arg( ap, char * ) )){
227 	M(ERRMSG,"GRAPH","problem with third argument\n" ) ;
228 	va_end(ap) ;
229 	return ;
230     }
231     /* need to make copy of format since scanner is destructive */
232     sprintf( copyformatS,"%s",control ) ;
233     tokenBuf = Ystrparser( copyformatS," \n\t\\", &numtokens ) ;
234     if( !(type = findType(tokenBuf,0)) ){
235 	M(ERRMSG,"GRAPH","Unknown control type.\n" ) ;
236 	va_end(ap) ;
237 	return ;
238     }
239     /* only print if graph has previously been flushed */
240     /* now that we have type we can get third element */
241     switch( type ){
242     case INT_TYPE:
243 	gint = va_arg( ap, INT ) ;
244 	if( gfileS[i].graphFlushed ){
245 	    fprintf( fp, tokenBuf[0], gint ) ;
246 	    fprintf( fp, "\t" ) ;
247 	}
248 	break ;
249     case CHAR_TYPE:
250 #ifdef linux
251 	gchar = (char) va_arg( ap, int ) ;
252 #else
253 	gchar = va_arg( ap, char ) ;
254 #endif
255 	if( gfileS[i].graphFlushed ){
256 	    fprintf( fp, tokenBuf[0], gchar ) ;
257 	    fprintf( fp, "\t" ) ;
258 	}
259 	break ;
260     case STRG_TYPE:
261 	gstr = va_arg( ap, char * ) ;
262 	if( gfileS[i].graphFlushed ){
263 	    fprintf( fp, tokenBuf[0], gstr ) ;
264 	    fprintf( fp, "\t" ) ;
265 	}
266 	break ;
267     case DOUB_TYPE:
268 	gdoub = va_arg( ap, DOUBLE ) ;
269 	if( gfileS[i].graphFlushed ){
270 	    fprintf( fp, tokenBuf[0], gdoub ) ;
271 	    fprintf( fp, "\t" ) ;
272 	}
273 	break ;
274     }
275     gfileS[i].graphFlushed = FALSE ;
276 
277 
278     /* fourth argument is control for yvariable */
279     if( !(format = va_arg( ap, char * ) )){
280 	M(ERRMSG,"GRAPH","problem with third argument\n" ) ;
281 	va_end(ap) ;
282 	return ;
283     }
284     /* need to make copy of format since scanner is destructive */
285     sprintf( copyformatS,"%s",format ) ;
286     tokenBuf = Ystrparser( copyformatS," \n\t\\", &numtokens ) ;
287     for( i = 0; i< numtokens; i++ ){
288 	if( !(type = findType(tokenBuf,i)) ){
289 	    M(ERRMSG,"GRAPH","Unknown control type.\n" ) ;
290 	    va_end(ap) ;
291 	    return ;
292 	}
293 	switch( type ){
294 	    case INT_TYPE:
295 		gint = va_arg( ap, INT ) ;
296 		fprintf( fp, tokenBuf[i], gint ) ;
297 		break ;
298 	    case CHAR_TYPE:
299 #ifdef linux
300 		gchar = (char) va_arg( ap, int ) ;
301 #else
302 		gchar = va_arg( ap, char ) ;
303 #endif
304 		fprintf( fp, tokenBuf[i], gchar ) ;
305 		break ;
306 	    case STRG_TYPE:
307 		gstr = va_arg( ap, char * ) ;
308 		fprintf( fp, tokenBuf[i], gstr ) ;
309 		break ;
310 	    case DOUB_TYPE:
311 		gdoub = va_arg( ap, DOUBLE ) ;
312 		fprintf( fp, tokenBuf[i], gdoub ) ;
313 		break ;
314 	}
315 	fprintf( fp, "\t" ) ;
316     }
317     va_end(ap) ;
318 
319 }
320 
Yplot_flush(char * gName)321 void Yplot_flush( char *gName )
322 {
323     INT i ;
324 
325     if( !(graphFilesS) ){
326 	/* don't do anything if flag is not set */
327 	return ;
328     }
329     if( gName ){
330 	for( i=0;i<gfilenoS;i++ ){
331 	    if( strcmp( gName, gfileS[i].fileName ) == STRINGEQ ){
332 		if(!(gfileS[i].graphFlushed)){
333 		    /* only flush if we have to */
334 		    fprintf( gfileS[i].fp, "\n" ) ;
335 		    fflush( gfileS[i].fp ) ;
336 		    gfileS[i].graphFlushed = TRUE ;
337 		}
338 		return ;
339 	    }
340 	}
341 	if( i >= gfilenoS ){
342 	    sprintf( YmsgG,
343 		"couldn't find file %s name in opened file list\n" ) ;
344 	    M(ERRMSG,"GRAPH", YmsgG ) ;
345 	    return ;
346 	}
347     } else { /* if null flush all files */
348 	for( i=0; i< gfilenoS ; i++ ){
349 	    if(!(gfileS[i].graphFlushed)){
350 		/* only flush if we have to */
351 		fprintf( gfileS[i].fp, "\n" ) ;
352 		fflush( gfileS[i].fp ) ;
353 		gfileS[i].graphFlushed = TRUE ;
354 	    }
355 	}
356     }
357 
358 } /* end GRAPHFLUSH */
359 
findType(control,number)360 static INT findType( control, number )
361 char **control ;
362 INT number ;
363 {
364     char *formatChar ;
365 
366     formatChar = control[number] ;
367     if( formatChar ){
368 
369 	if( strchr(formatChar,'d') ){
370 	    return( INT_TYPE ) ;
371 	} else if( strchr(formatChar,'f') ){
372 	    return( DOUB_TYPE ) ;
373 	} else if( strchr(formatChar,'e') ){
374 	    return( DOUB_TYPE ) ;
375 	} else if( strchr(formatChar,'s') ){
376 	    return( STRG_TYPE ) ;
377 	} else if( strchr(formatChar,'c') ){
378 	    return( CHAR_TYPE ) ;
379 	}
380     }
381     return( NULL_TYPE ) ;
382 } /* end findType */
383 
384 
385 #ifdef TEST
386 
main()387 main()
388 {
389     INT i ;       /* counter */
390     DOUBLE f ;    /* function value */
391     INT y ;       /* integer function value */
392 
393     /* first initialize two graphs */
394     Yplot_init( 0, "graph1", "graph_kroy", NULL ) ;
395 
396     /* -------------------------------------------------------------
397        Now set the heading for the graph.
398        YgraphHeading can be call multiple times but first time will
399        be what is output to the graph file.  Remember the Nulls at end.
400     ---------------------------------------------------------------- */
401     for( i = 1; i <= 10; i++ ){
402 	/* set the first graph heading. It is good to keep heading with */
403 	/* output so it is easy to read the arguments to Ygraph */
404 	Yplot_heading( 0, "graph1", "x_axis", "f(x)", "y2", NULL ) ;
405 	/* -------------------------------------------------------------
406 	   Ygraph has the following format:
407 	   Ygraph( filename, x format, x varible, y format, y variables...
408 	------------------------------------------------------------- */
409 	f = (DOUBLE) i ;
410 	y = i * i ;
411 	Yplot( 0, "graph1", "%d", i, "%4.2le %d", f, y ) ;
412 	/* now after each graph has been finished flush data */
413 	Yplot_flush( "graph1" ) ;
414 
415 	/* now output another graph */
416 	Yplot_heading( 0, "graph_kroy", "iter", "Temperature", NULL ) ;
417 	Yplot( 0, "graph_kroy", "%4.2le", (DOUBLE) i, "%d", 3 * i ) ;
418 	Yplot_flush( "graph_kroy" ) ;
419     }
420 
421     /* When we are done with the graph close them */
422     Yplot_close() ;
423 
424     exit(0) ;
425 }
426 
427 #endif /* TEST */
428 
429