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