1 /******************************************************************************
2  * DESCRIPTION: Dinotrace source: configuration file reading
3  *
4  * This file is part of Dinotrace.
5  *
6  * Author: Wilson Snyder <wsnyder@wsnyder.org>
7  *
8  * Code available from: http://www.veripool.org/dinotrace
9  *
10  ******************************************************************************
11  *
12  * Some of the code in this file was originally developed for Digital
13  * Semiconductor, a division of Digital Equipment Corporation.  They
14  * gratefuly have agreed to share it, and thus the base version has been
15  * released to the public with the following provisions:
16  *
17  *
18  * This software is provided 'AS IS'.
19  *
20  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THE INFORMATION
21  * (INCLUDING ANY SOFTWARE) PROVIDED, INCLUDING ALL IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR ANY PARTICULAR PURPOSE, AND
23  * NON-INFRINGEMENT. DIGITAL NEITHER WARRANTS NOR REPRESENTS THAT THE USE
24  * OF ANY SOURCE, OR ANY DERIVATIVE WORK THEREOF, WILL BE UNINTERRUPTED OR
25  * ERROR FREE.  In no event shall DIGITAL be liable for any damages
26  * whatsoever, and in particular DIGITAL shall not be liable for special,
27  * indirect, consequential, or incidental damages, or damages for lost
28  * profits, loss of revenue, or loss of use, arising out of or related to
29  * any use of this software or the information contained in it, whether
30  * such damages arise in contract, tort, negligence, under statute, in
31  * equity, at law or otherwise. This Software is made available solely for
32  * use by end users for information and non-commercial or personal use
33  * only.  Any reproduction for sale of this Software is expressly
34  * prohibited. Any rights not expressly granted herein are reserved.
35  *
36  ******************************************************************************
37  *
38  * Changes made over the basic version are covered by the GNU public licence.
39  *
40  * Dinotrace is free software; you can redistribute it and/or modify
41  * it under the terms of the GNU General Public License as published by
42  * the Free Software Foundation; either version 3, or (at your option)
43  * any later version.
44  *
45  * Dinotrace is distributed in the hope that it will be useful,
46  * but WITHOUT ANY WARRANTY; without even the implied warranty of
47  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
48  * GNU General Public License for more details.
49  *
50  * You should have received a copy of the GNU General Public License
51  * along with Dinotrace; see the file COPYING.  If not, write to
52  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
53  * Boston, MA 02111-1307, USA.
54  *
55  ******************************************************************************
56 # Undocumented:
57 #	debug		ON | OFF
58 #	print		<number> | ON | OFF
59 #
60 #	# Comment
61 # Config:
62 #	click_to_edge	ON | OFF
63 #	cursor		ON | OFF
64 #	refreshing	AUTO | MANUAL
65 #	grid		<grid_number>	ON | OFF
66 #	grid_align	<grid_number>	<number> | ASSERTION | DEASSERTION
67 #	grid_resolution	<grid_number>	<number> | AUTO | EDGE
68 #	grid_type	<grid_number>	NORMAL | WIDE
69 #	grid_signal	<grid_number>	<signal_pattern>
70 #	grid_color	<grid_number>	<color>
71 #	page_inc	4 | 2 | 1
72 #	print_size	A | B | EPSPORT | EPSLAND
73 #	rise_fall_time	<number>
74 #	signal_height	<number>
75 #	time_format	%0.6lf | %0.6lg | ""
76 #	time_precision	US | NS | PS | FS
77 #	time_rep	<number> | US | NS | PS | FS | CYCLE
78 # File Format:
79 #	file_format	DECSIM | TEMPEST | VERILOG
80 #	save_enables	ON | OFF
81 #	save_ordering	ON | OFF
82 #	save_duplicates	ON | OFF
83 #	signal_states	<signal_pattern> = {<State>, <State>...}
84 #	vector_separator "<char>"
85 #	hierarchy_separator "<chars>"
86 #       time_multiplier	<number>
87 # Geometry/resources:
88 #	open_geometry	<width>[%]x<height>[%]+<xoffset>[%]+<yoff>[%]
89 #	shrink_geometry	<width>%x<height>%+<xoffset>%+<yoff>%
90 #	start_geometry	<width>x<height>+<xoffset>+<yoffset>
91 # Modification of traces:
92 #	signal_delete	<signal_pattern>
93 #	signal_delete_constant	<signal_pattern> [-IGNOREXZ]
94 #	signal_add	<signal_pattern>	[<after_signal_first_matches>]	[<color>]
95 #	signal_copy	<signal_pattern>	[<after_signal_first_matches>]	[<color>]
96 #	signal_move	<signal_pattern>	[<after_signal_first_matches>]	[<color>]
97 #	signal_radix	<signal_pattern> <HEX|BINARY|OCT|ASCII|DEC>
98 #	signal_waveform	<signal_pattern> <DIGITAL|ANALOG|ANALOG_SIGNED>
99 #	signal_rename	<signal_pattern> <new_signal_name>	[<color>]
100 #	signal_highlight <signal_pattern> <color>
101 #	signal_note	<signal_pattern> <note>
102 #	cursor_add	<time> <color>	[-USER]
103 #	value_highlight <value>	<color>	[<signal_pattern>] [-CURSOR] [-VALUE]
104 # Display changes:
105 #	signal_goto	<signal_pattern>	(if not on screen, first match)
106 #	time_goto	<time>
107 #	resolution	<res>
108 #	refresh
109 #	annotate
110  *****************************************************************************/
111 
112 
113 #include "dinotrace.h"
114 
115 #include "functions.h"
116 
117 /**********************************************************************/
118 
119 /* See the ascii map to have this make sense */
120 #define issigchr(ch)  ( ((ch)>' ') && ((ch)!='=') && ((ch)!='\"')  && ((ch)!='\'') )
121 
122 #define isstatechr(ch)  ( ((ch)>' ') && ((ch)!=',') && ((ch)!='=') && ((ch)!='{') && ((ch)!='}') && ((ch)!='\"') && ((ch)!='\'') )
123 
124 #define isstatesep(ch)  (!isstatechr(ch) && (ch)!='}' )
125 
126 
127 /* File locals */
128 static Boolean_t config_report_errors;
129 static char *config_file="";
130 static int config_line_num=0;
131 static Boolean_t config_reading_socket;
132 
133 /**********************************************************************
134  * Utils
135  */
136 
config_error_ack(Trace_t * trace,char * message)137 void	config_error_ack (
138     Trace_t	*trace,
139     char	*message)
140 {
141     char	newmessage[1000];
142 
143     if (!config_report_errors) return;
144 
145     strcpy (newmessage, message);
146     if (config_reading_socket) {
147 	sprintf (newmessage + strlen(newmessage), "on command # %d from socket %s\n", config_line_num, config_file);
148     }
149     else {
150 	sprintf (newmessage + strlen(newmessage), "on line %d of %s\n", config_line_num, config_file);
151     }
152     dino_error_ack (trace, newmessage);
153 }
154 
155 /**********************************************************************
156 *	READING FUNCTIONS
157 **********************************************************************/
158 
config_get_line(char * line,int len,FILE * readfp)159 static void config_get_line (
160     char *line,
161     int len,
162     FILE *readfp)
163 {
164     char *tp;
165 
166     /* Read line & kill EOL at end */
167     fgets (line, len, readfp);
168     if (*line && *(tp=(line+strlen(line)-1))=='\n') *tp='\0';
169     config_line_num++;
170 }
171 
config_read_string(Trace_t * trace,char * line,char * out)172 static int config_read_string (
173     Trace_t *trace,
174     char *line,
175     char *out)
176 {
177     int outlen=0;
178     Boolean_t quote = FALSE;
179 
180     while (*line && isspace(*line)) {
181 	line++; outlen++;
182     }
183 
184     if (*line=='"') {
185 	line++; outlen++;
186 	quote = TRUE;
187     }
188 
189     while (*line && (quote ? *line!='"' : issigchr(*line))) {
190 	if (*line == '\\') {
191 	    line++;
192 	    outlen++;
193 	    switch (*line) {
194 	    case '\0':
195 		line--;
196 		break;
197 	    case 'n':
198 		*out++ = '\n';
199 		break;
200 	    default:
201 		*out++ = *line;
202 	    }
203 	}
204 	else {
205 	    *out++ = *line;
206 	}
207 	line++; outlen++;
208     }
209 
210     if (quote) {
211 	if (*line == '"') {
212 	    line++; outlen++;
213 	} else {
214 	    config_error_ack (trace, "Double quotes aren't terminated\n");
215 	}
216     }
217     *out++ = '\0';
218     return (outlen);
219 }
220 
config_read_value(Trace_t * trace,char * line,char * out)221 static int config_read_value (
222     Trace_t *trace,
223     char *line,
224     char *out)
225 {
226     int outlen=0;
227     Boolean_t quote = FALSE;
228 
229     while (*line && isspace(*line)) {
230 	line++; outlen++;
231     }
232 
233     if (*line=='"') {
234 	*out++ = *line;
235 	line++; outlen++;
236 	quote = TRUE;
237     }
238 
239     while (*line && (quote ? *line!='"' : !isspace(*line))) {
240 	if (*line == '\\') {
241 	    line++;
242 	    outlen++;
243 	    switch (*line) {
244 	    case '\0':
245 		line--;
246 		break;
247 	    case 'n':
248 		*out++ = '\n';
249 		break;
250 	    default:
251 		*out++ = *line;
252 	    }
253 	}
254 	else {
255 	    *out++ = *line;
256 	}
257 	line++; outlen++;
258     }
259 
260     if (quote) {
261 	if (*line == '"') {
262 	    *out++ = *line;
263 	    line++; outlen++;
264 	} else {
265 	    config_error_ack (trace, "Double quotes aren't terminated\n");
266 	}
267     }
268     *out++ = '\0';
269     return (outlen);
270 }
271 
config_read_pattern(Trace_t * trace,char * line,char * pattern)272 static int config_read_pattern (
273     Trace_t	*trace,
274     char *line,
275     char *pattern)
276 {
277     int outlen;
278     outlen = config_read_string (trace, line, pattern);
279     if (!pattern[0]) {
280         config_error_ack (trace, "Signal pattern name must not be null\n");
281     }
282     return (outlen);
283 }
284 
config_read_state(char * line,char * out,int * statenum_ptr)285 static int config_read_state (
286     char *line,
287     char *out,
288     int *statenum_ptr)
289 {
290     char *tp;
291     int outlen=0;
292 
293     while (*line && isstatesep(*line)) {
294 	line++;
295 	outlen++;
296     }
297 
298     if (!*line) {
299 	out[0]='\0';
300 	return(outlen);
301     }
302 
303     for (tp=line; *tp && isdigit(*tp); tp++) ;
304     if (*tp++ == '=') {
305 	/* 22=statename type assignment */
306 	*statenum_ptr = atoi (line);
307 	outlen += (tp - line);
308 	line = tp;
309     }
310 
311     /* extract state */
312     strncpy(out, line, MAXVALUELEN);
313     out[MAXVALUELEN-1]='\0';
314     for (tp=out; *tp && isstatechr(*tp); tp++) ;
315     *tp='\0';
316 
317     return (strlen(out)+outlen);
318 }
319 
config_read_int(char * line,int * out)320 static int config_read_int (
321     char *line,
322     int *out)
323 {
324     int outlen=0;
325 
326     while (*line && !isalnum(*line) && *line!='-') {
327 	line++;
328 	outlen++;
329     }
330 
331     if (!*line) {
332 	*out=0;
333 	return(outlen);
334     }
335 
336     /* extract command */
337     *out = atoi(line);
338     while (*line && isdigit(*line)) {
339 	line++;
340 	outlen++;
341     }
342 
343     return (outlen);
344 }
345 
346 
347 /**********************************************************************
348 *	SUPPORT FUNCTIONS
349 **********************************************************************/
350 
signalstate_find(const Trace_t * trace,const char * name)351 SignalState_t	*signalstate_find (
352     const Trace_t	*trace,
353     const char *name)
354 {
355     register SignalState_t *sig;
356 
357     for (sig=global->signalstate_head; sig; sig=sig->next) {
358 	/* printf ("'%s'\t'%s'\n", name, sig->signame); */
359 	if (wildmat(name, sig->signame))
360 	    return (sig);
361     }
362     return (NULL);
363 }
364 
signalstate_add(Trace_t * trace,SignalState_t * info)365 static void	signalstate_add (
366     Trace_t	*trace,
367     SignalState_t *info)
368 {
369     SignalState_t *newp;
370     int t;
371 
372     for (newp = global->signalstate_head; newp ; newp=newp->next) {
373       if (!strcmp (newp->signame, info->signame)) break;
374     }
375     if (! newp) {
376       /* Not found, add & relink */
377       newp = XtNew (SignalState_t);
378       memcpy ((void *)newp, (void *)info, sizeof(SignalState_t));
379       newp->next = global->signalstate_head;
380       global->signalstate_head = newp;
381       draw_needupd_val_states ();
382     }
383     else {
384       /* Found, overwrite old */
385       info->next = newp->next;	/* Don't loose the link */
386       memcpy ((void *)newp, (void *)info, sizeof(SignalState_t));
387     }
388 
389     /*printf ("Signal '%s' Assigned States:\n", newp->signame);*/
390     for (t=0; t<MAXSTATENAMES; t++) {
391 	if (newp->statename[t][0] != '\0') {
392 	    newp->numstates = t+1;
393 	    /*printf ("State %d = '%s'\n", t, newp->statename[t]);*/
394 	}
395     }
396 }
397 
signalstate_free(void)398 static void	signalstate_free (void)
399 {
400     SignalState_t *sstate_ptr, *last_ptr;
401 
402     sstate_ptr = global->signalstate_head;
403     while (sstate_ptr) {
404 	last_ptr = sstate_ptr->next;
405 	DFree (sstate_ptr);
406 	sstate_ptr = last_ptr;
407     }
408     global->signalstate_head = NULL;
409 }
410 
signalstate_write(FILE * writefp,const char * c)411 static void	signalstate_write (
412     FILE *writefp, const char *c)
413 {
414     SignalState_t *sstate_ptr;
415     int i;
416 
417     fprintf (writefp, "\n#### Global Signal States ####\n");
418 
419     for (sstate_ptr = global->signalstate_head;
420 	 sstate_ptr; sstate_ptr = sstate_ptr->next) {
421 	fprintf (writefp, "%ssignal_states %s {\n",c,sstate_ptr->signame);
422 	for (i=0; i<MAXSTATENAMES; i++) {
423 	    if (sstate_ptr->statename[i][0]) {
424 		fprintf (writefp, "%s\t%d=\"%s\",\n",c, i, sstate_ptr->statename[i]);
425 	    }
426 	}
427 	fprintf (writefp, "%s\t}\n",c);
428     }
429     fprintf (writefp,"\n");
430 }
431 
config_parse_geometry(char * line,Geometry_t * geometry)432 void	config_parse_geometry (
433     char	*line,
434     Geometry_t	*geometry)
435     /* Like XParseGeometry, but handles percentages */
436 {
437     int		flags;
438     int		x,y;
439     uint_t	wid, hei;
440     char	noper_line[100];
441     char	*tp;
442 
443     /* Copy line into a temp, remove the percentage symbols, and parse it */
444     strcpy (noper_line, line);
445     while ((tp=strchr (noper_line, '%'))) strcpy_overlap (tp, tp+1);
446 
447     flags = XParseGeometry (noper_line, &x, &y, &wid, &hei);
448     if (flags & WidthValue)	geometry->width = wid;
449     if (flags & HeightValue)	geometry->height = hei;
450     if (flags & XValue)		geometry->x = x;
451     if (flags & YValue)		geometry->y = y;
452 
453     /* Now figure out what the percentage symbols apply to */
454     geometry->xp = geometry->yp = geometry->heightp = geometry->widthp = FALSE;
455     for (tp = line; *tp; ) {
456 	while (*tp && !isdigit(*tp)) tp++;
457 	while (isdigit(*tp)) tp++;
458 	if (*tp=='%') {
459 	    if (flags & WidthValue)	geometry->widthp = TRUE;
460 	    else if (flags & HeightValue) geometry->heightp = TRUE;
461 	    else if (flags & XValue)	geometry->xp = TRUE;
462 	    else if (flags & YValue)	geometry->yp = TRUE;
463 	}
464 	if (flags & WidthValue) 	flags &= flags & (~ WidthValue);
465 	else if (flags & HeightValue)	flags &= flags & (~ HeightValue);
466 	else if (flags & XValue)	flags &= flags & (~ XValue);
467 	else if (flags & YValue)	flags &= flags & (~ YValue);
468     }
469 
470     if (DTPRINT_CONFIG) printf ("geometry %s = %dx%d+%d+%d   %c%c%c%c\n", line,
471 				geometry->width, geometry->height,
472 				geometry->x, geometry->y,
473 				geometry->widthp?'%':'-', geometry->heightp?'%':'-',
474 				geometry->xp?'%':'-', geometry->yp?'%':'-');
475 }
476 
config_geometry_string(Geometry_t * geometry,char * strg)477 static void	config_geometry_string (
478     Geometry_t	*geometry,
479     char *strg)
480 {
481     sprintf (strg, "%d%sx%d%s+%d%s+%d%s",
482 	     geometry->width,	geometry->widthp?"%":"",
483 	     geometry->height,	geometry->heightp?"%":"",
484 	     geometry->x,	geometry->xp?"%":"",
485 	     geometry->y,	geometry->xp?"%":"");
486 }
487 
488 
489 /**********************************************************************
490 *	reading functions w/ error messages
491 **********************************************************************/
492 
config_read_on_off(Trace_t * trace,char * line,int * out)493 static int	config_read_on_off (
494     Trace_t	*trace,
495     char *line,
496     int *out)
497     /* Read boolean flag line, return <= 0 and print msg if bad */
498 {
499     char cmd[MAXSIGLEN];
500     int outlen;
501 
502     outlen = config_read_string (trace, line, cmd);
503 
504     if (!strcasecmp (cmd, "ON") || !strcmp (cmd, "1"))
505 	*out = 1;
506     else if (!strcasecmp (cmd, "OFF") || !strcmp (cmd, "0"))
507 	*out = 0;
508     else {
509 	sprintf (message, "Expected ON or OFF switch\n");
510 	config_error_ack (trace, message);
511 	*out = -1;
512     }
513 
514     return (outlen);
515 }
516 
config_read_color(Trace_t * trace,char * line,ColorNum_t * color,Boolean_t warn)517 static int	config_read_color (
518     Trace_t	*trace,
519     char 	*line,
520     ColorNum_t	*color,
521     Boolean_t	warn)
522     /* Read color name from line, return <= 0 and print msg if bad */
523 {
524     int outlen=0;
525     char cmd[MAXSIGLEN];
526 
527     while (*line && isspace(*line)) {
528 	line++; outlen++;
529     }
530 
531     switch (*line) {
532     case 'N': case 'n':
533 	outlen += config_read_string (trace, line, cmd);
534 	*color = global->highlight_color;
535 	break;
536     case 'C': case 'c':
537 	/* Duplicate code in submenu_to_color */
538 	outlen += config_read_string (trace, line, cmd);
539 	if ((++global->highlight_color) > MAX_SRCH) global->highlight_color = 1;
540 	*color = global->highlight_color;
541 	break;
542     case '0': case '1': case '2':case '3':case '4':
543     case '5': case '6': case '7':case '8':case '9':
544 	outlen += config_read_int (line, color);
545 	if (*color < 0 || *color > MAX_SRCH) {
546 	    if (warn) {
547 		sprintf (message, "Color numbers must be 0 to %d, NEXT or CURRENT\n", MAX_SRCH);
548 		config_error_ack (trace, message);
549 	    }
550 	    *color = -1;
551 	}
552 	break;
553     default:
554 	*color = -1;
555 	break;
556     }
557 
558     return (outlen);
559 }
560 
config_read_grid(Trace_t * trace,char * line,Grid_t ** grid_pptr)561 int	config_read_grid (
562     Trace_t	*trace,
563     char 	*line,
564     Grid_t	**grid_pptr)
565     /* Read grid number name from line, return < 0 and print msg if bad */
566 {
567     int 	outlen;
568     int		grid_num;
569     char	message [100];
570 
571     outlen = config_read_int (line, &grid_num);
572 
573     if (grid_num < 0 || grid_num > MAXGRIDS) {
574 	sprintf (message, "Grid numbers must be 0 to %d\n", MAXGRIDS);
575 	grid_num = -1;
576 	*grid_pptr = NULL;
577     }
578     else {
579 	*grid_pptr = &(trace->grid[grid_num]);
580     }
581 
582     return (outlen);
583 }
584 
585 /**********************************************************************
586 *	config_process_states
587 **********************************************************************/
588 
config_process_state(Trace_t * trace,char * line,SignalState_t * sstate_ptr)589 static int config_process_state (
590     Trace_t	*trace,
591     char 	*line,
592     SignalState_t *sstate_ptr)
593 {
594     char newstate[MAXVALUELEN];
595     int	statenum = sstate_ptr->numstates;
596     int outlen=0;
597 
598     if (*line && *line!='}') {
599 	outlen = config_read_state (line, newstate, &statenum);
600 	line += outlen;
601 	/*printf ("Got = %d '%s'\n", statenum, newstate);*/
602 	if (statenum < 0 || statenum >= MAXSTATENAMES) {
603 	    sprintf (message, "Over maximum of %d SIGNAL_STATES for signal %s\n",
604 		     MAXSTATENAMES, sstate_ptr->signame);
605 	    config_error_ack (trace,message);
606 	    /* No return, as will just ignore remaining errors */
607 	}
608 	else {
609 	    if (newstate[0]) {
610 		sstate_ptr->numstates = statenum+1;
611 		strcpy (sstate_ptr->statename[statenum], newstate);
612 	    }
613 	}
614     }
615     return (outlen);
616 }
617 
618 
619 /**********************************************************************
620 *	config_process_line
621 **********************************************************************/
622 
config_process_line_internal(Trace_t * trace,char * line,Boolean_t format_only,Boolean_t eof)623 static void	config_process_line_internal (
624     Trace_t	*trace,
625     char	*line,
626     Boolean_t	format_only,
627     Boolean_t	eof)		/* Final call of process_line with EOF */
628 {
629     char cmd[MAXSIGLEN];
630     int value;
631     Grid_t	*grid_ptr;
632     char pattern[MAXSIGLEN];
633     char *cmt;
634 
635     static SignalState_t newsigst;
636     static Boolean_t processing_sig_state = FALSE;
637 
638   re_process_line:
639 
640     /* Strip spaces and comments */
641     while (*line && isspace(*line)) line++;
642     cmt = line;
643     while (cmt != NULL) {
644 	cmt=strpbrk(cmt,"!#\"");
645 	if (cmt!=NULL) {
646 	    if (*cmt=='\"') {
647 		cmt=strpbrk(cmt+1,"\"");	/* Skip to closing quote */
648 		continue;
649 	    }
650 	    *cmt = '\0';
651 	    break;
652 	}
653     }
654     if ((line[0]==';') || (line[0]=='\0')) return;
655 
656     /* if (DTPRINT_CONFIG) printf ("Cmd='%s'\n",cmd); */
657 
658     if (processing_sig_state) {
659 	if (*line == ';' || *line=='}' || eof) {
660 	    if (eof) {
661 		config_error_ack (trace, "Unexpected EOF during SIGNAL_STATES\n");
662 	    }
663 	    signalstate_add (trace, &newsigst);
664 	    processing_sig_state = FALSE;
665 	}
666 	else {
667 	    line += config_process_state (trace, line, &newsigst);
668 	    goto re_process_line;
669 	}
670     }
671     else {
672 	/* General commands */
673 
674 	/* Preprocessor #INCLUDE eventually */
675 	/* extract command */
676 	line += config_read_string (trace, line, cmd);
677 	while (*line && isspace(*line)) line++;
678 	upcase_string (cmd);
679 
680 	if (!strcmp(cmd, "DEBUG")) {
681 	    value=DTDEBUG;
682 	    line += config_read_on_off (trace, line, &value);
683 	    if (value >= 0) {
684 		if (DTPRINT) printf ("Config: DTDEBUG=%d\n",value);
685 		DTDEBUG=value;
686 	    }
687 	}
688 	else if (!strcmp(cmd, "PRINT")) {
689 	    value=DTPRINT;
690 	    if (toupper(line[0])=='O' && toupper(line[1])=='N') DTPRINT = ~0;
691 	    else if (toupper(line[0])=='O' && toupper(line[1])=='F') DTPRINT = 0;
692 	    else {
693 		sscanf (line, "%x", &value);
694 		if (value > 0) {
695 		    DTPRINT=value;
696 		}
697 		else {
698 		    config_error_ack (trace, "Print must be set ON, OFF, or > 0\n");
699 		}
700 	    }
701 	    if (DTPRINT) printf ("Config: DTPRINT=0x%x\n",value);
702 	}
703 	/************************************************************/
704 	/* Commands needed before a file is read */
705 	/* These should be only global or dfile parameters (not trace parameters) */
706 	else if (!strcmp(cmd, "FILE_FORMAT")) {
707 	    char *tp;
708 	    for (tp = line; *tp && *tp!='Z' && *tp!='z'; tp++) ;
709 	    switch (toupper(line[0])) {
710 	      case 'D':
711 		file_format = FF_DECSIM;
712 		break;
713 	      case 'T':
714 		file_format = FF_TEMPEST;
715 		break;
716 	      case 'V':
717 		if (toupper(line[1]) == 'P') {
718 		    file_format = FF_VERILOG_VPD;
719 		} else {
720 		    file_format = FF_VERILOG;
721 		}
722 		break;
723 	      default:
724 		config_error_ack (trace, "File_Format must be DECSIM, TEMPEST, VPD or VERILOG\n");
725 	    }
726 	    if (DTPRINT_CONFIG) printf ("File_format = %d\n", file_format);
727 	}
728 	else if (!strcmp(cmd, "SAVE_ENABLES")) {
729 	    value=global->save_enables;
730 	    line += config_read_on_off (trace, line, &value);
731 	    if (value >= 0) {
732 		global->save_enables=value;
733 	    }
734 	}
735 	else if (!strcmp(cmd, "SAVE_ORDERING")) {
736 	    value=global->save_ordering;
737 	    line += config_read_on_off (trace, line, &value);
738 	    if (value >= 0) {
739 		global->save_ordering=value;
740 	    }
741 	}
742 	else if (!strcmp(cmd, "SAVE_DUPLICATES")) {
743 	    value=global->save_duplicates;
744 	    line += config_read_on_off (trace, line, &value);
745 	    if (value >= 0) {
746 		global->save_duplicates=value;
747 	    }
748 	}
749 	else if (!strcmp(cmd, "TIME_REP")) {
750 	    switch (toupper(line[0])) {
751 	      case 'N':	global->timerep = TIMEREP_NS;	break;
752 	      case 'U':	global->timerep = TIMEREP_US;	break;
753 	      case 'P':	global->timerep = TIMEREP_PS;	break;
754 	      case 'F':	global->timerep = TIMEREP_FS;	break;
755 	      case 'C':	global->timerep = TIMEREP_CYC;	break;
756 	      case '0': case '1': case '2': case '3': case '4':
757 	      case '5': case '6': case '7': case '8': case '9': case '.':
758 		global->timerep = atof(line);	break;
759 	      default:
760 		config_error_ack (trace, "Time_Rep must be FS, PS, NS, US, or CYCLE\n");
761 	    }
762 	    if (DTPRINT_CONFIG) printf ("timerep = %f\n", global->timerep);
763 	}
764 	else if (!strcmp(cmd, "TIME_PRECISION")) {
765 	    switch (toupper(line[0])) {
766 	      case 'N':	global->time_precision = TIMEREP_NS;	break;
767 	      case 'U':	global->time_precision = TIMEREP_US;	break;
768 	      case 'P':	global->time_precision = TIMEREP_PS;	break;
769 	      case 'F':	global->time_precision = TIMEREP_FS;	break;
770 	      default:
771 		config_error_ack (trace, "Time_Precision must be FS, PS, NS, or US\n");
772 	    }
773 	    if (DTPRINT_CONFIG) printf ("time_precision = %f\n", global->time_precision);
774 	}
775 	else if (!strcmp(cmd, "TIME_FORMAT")) {
776 	    line += config_read_string (trace, line, cmd);
777 	    strcpy (global->time_format, cmd);
778 	    if (DTPRINT_CONFIG) printf ("time_format = '%s'\n", global->time_format);
779 	}
780 	else if (!strcmp(cmd, "TIME_MULTIPLIER")) {
781 	    value = global->tempest_time_mult;
782 	    line += config_read_int (line, &value);
783 	    if (value > 0) global->tempest_time_mult = value;
784 	    else {
785 		config_error_ack (trace, "Time_Mult must be > 0\n");
786 	    }
787 	}
788 	else if (!strcmp(cmd, "HIERARCHY_SEPARATOR")) {
789 	    line += config_read_string (trace, line, pattern);
790 	    if (pattern[0]) {
791 		trace->dfile.hierarchy_separator = pattern[0];
792 	    }
793 	}
794 	else if (!strcmp(cmd, "VECTOR_SEPERATOR")	/* Backward compatible spelling! */
795 		 || !strcmp(cmd, "VECTOR_SEPARATOR")) {
796 	    if (*line=='"') line++;
797 	    if (*line && *line!='"') {
798 		trace->dfile.vector_separator = line[0];
799 	    }
800 	    else {
801 		trace->dfile.vector_separator = '\0';
802 	    }
803 	    /* Take a stab at the ending character */
804 	    switch (trace->dfile.vector_separator) {
805 	      case '`':	trace->dfile.vectorend_separator = '\''; break;
806 	      case '(':	trace->dfile.vectorend_separator = ')'; break;
807 	      case '[':	trace->dfile.vectorend_separator = ']'; break;
808 	      case '{':	trace->dfile.vectorend_separator = '}'; break;
809 	      case '<':	trace->dfile.vectorend_separator = '>'; break;
810 	      default:  trace->dfile.vectorend_separator = trace->dfile.vector_separator; break;	/* a wild guess SIG$20:1$? */
811 	    }
812 	    if (DTPRINT_CONFIG) printf ("vector_separator = '%c'  End='%c'\n",
813 					trace->dfile.vector_separator, trace->dfile.vectorend_separator);
814 	}
815 	else if (format_only) {
816 	    return;
817 	}
818 	/**************************************************************/
819 	/** beginning of non-file_format commands */
820 	/**************************************************************/
821 	else if (!strcmp(cmd, "CURSOR")) {
822 	    value = global->cursor_vis;
823 	    line += config_read_on_off (trace, line, &value);
824 	    if (value >= 0) {
825 		if (DTPRINT_CONFIG) printf ("Config: cursor_vis=%d\n",value);
826 		global->cursor_vis = value;
827 	    }
828 	}
829 	else if (!strcmp(cmd, "CLICK_TO_EDGE")) {
830 	    value = global->click_to_edge;
831 	    line += config_read_on_off (trace, line, &value);
832 	    if (value >= 0) {
833 		if (DTPRINT_CONFIG) printf ("Config: click_to_edge=%d\n",value);
834 		global->click_to_edge = value;
835 	    }
836 	}
837 	else if (!strcmp(cmd, "DRAW_PREFIX")) {
838 	    value = global->prefix_enable;
839 	    line += config_read_on_off (trace, line, &value);
840 	    if (value >= 0) {
841 		global->prefix_enable = value;
842 	    }
843 	}
844 	else if (!strcmp(cmd, "REFRESHING")) {
845 	    if (toupper(line[0])=='A')
846 		global->redraw_manually = FALSE;
847 	    else if (toupper(line[0])=='M')
848 		global->redraw_manually = TRUE;
849 	    else {
850 		config_error_ack (trace, "Refreshing must be AUTO, or MANUAL\n");
851 	    }
852 	}
853 	else if (!strcmp(cmd, "SIGNAL_HEIGHT")) {
854 	    value = global->sighgt;
855 	    line += config_read_int (line, &value);
856 	    if (value >= 10 && value <= 50)
857 		global->sighgt = value;
858 	    else {
859 		config_error_ack (trace, "Signal_height must be 10-50\n");
860 	    }
861 	}
862 	else if (!strcmp(cmd, "GRID")) {
863 	    line += config_read_grid (trace, line, &grid_ptr);
864 	    line += config_read_on_off (trace, line, &value);
865 	    if (grid_ptr && value >= 0) {
866 		if (DTPRINT_CONFIG) printf ("Config: grid_vis=%d\n",value);
867 		grid_ptr->visible = value;
868 	    }
869 	}
870 	else if (!strcmp(cmd, "GRID_RESOLUTION")) {
871 	    line += config_read_grid (trace, line, &grid_ptr);
872 	    line += config_read_string (trace, line, pattern);
873 	    if (grid_ptr) {
874 		if (isalpha(pattern[0])) {
875 		    if (toupper(pattern[0])=='A')
876 			grid_ptr->period_auto = PA_AUTO;
877 		    else if (toupper(pattern[0])=='E')
878 			grid_ptr->period_auto = PA_EDGE;
879 		    else {
880 			config_error_ack (trace, "Grid_res must be >0, AUTO or EDGE\n");
881 		    }
882 		}
883 		else {
884 		    value = string_to_time (trace, pattern);
885 		    grid_ptr->period = value;
886 		    grid_ptr->period_auto = PA_USER;
887 		}
888 	    }
889 	}
890 	else if (!strcmp(cmd, "GRID_ALIGN")) {
891 	    line += config_read_grid (trace, line, &grid_ptr);
892 	    line += config_read_string (trace, line, pattern);
893 	    if (isalpha(pattern[0])) {
894 		if (toupper(pattern[0])=='A')
895 		    grid_ptr->align_auto = AA_ASS;
896 		else if (toupper(pattern[0])=='D')
897 		    grid_ptr->align_auto = AA_DEASS;
898 		else if (toupper(pattern[0])=='B')
899 		    grid_ptr->align_auto = AA_BOTH;
900 		else {
901 		    config_error_ack (trace, "Grid_align must be >0, ASSERTION, or DEASSERTION, or BOTH\n");
902 		}
903 	    }
904 	    else {
905 		value = string_to_time (trace, pattern);
906 		grid_ptr->alignment = value;
907 		grid_ptr->align_auto = AA_USER;
908 	    }
909 	}
910 	else if (!strcmp(cmd, "GRID_TYPE")) {
911 	    line += config_read_grid (trace, line, &grid_ptr);
912 	    line += config_read_int (line, &value);
913 	    if (isalpha(line[0])) { line += config_read_string (trace, line, pattern); }
914 	    if (grid_ptr) {
915 		if (toupper(pattern[0])=='N')
916 		    grid_ptr->wide_line = FALSE;
917 		else if (toupper(pattern[0])=='W')
918 		    grid_ptr->wide_line = TRUE;
919 		else {
920 		    config_error_ack (trace, "Grid_type must be NORMAL or WIDE\n");
921 		}
922 	    }
923 	}
924 	else if (!strcmp(cmd, "GRID_SIGNAL")) {
925 	    line += config_read_grid (trace, line, &grid_ptr);
926 	    line += config_read_string (trace, line, pattern);
927 	    if (grid_ptr && *pattern) {
928 		strcpy (grid_ptr->signal, pattern);
929 	    }
930 	}
931 	else if (!strcmp(cmd, "GRID_COLOR")) {
932 	    ColorNum_t color;
933 	    line += config_read_grid (trace, line, &grid_ptr);
934 	    line += config_read_color (trace, line, &color, TRUE);
935 	    if (grid_ptr && color>=0) {
936 		grid_ptr->color = color;
937 	    }
938 	}
939 	else if (!strcmp(cmd, "RISE_FALL_TIME")) {
940 	    value = global->sigrf;
941 	    line += config_read_int (line, &value);
942 	    /* Valid values not known... */
943 	    global->sigrf = value;
944 	}
945 	else if (!strcmp(cmd, "PAGE_INC")) {
946 	    value = global->pageinc;
947 	    line += config_read_int (line, &value);
948 	    if (value == 1) global->pageinc = PAGEINC_FULL;
949 	    else if (value == 2) global->pageinc = PAGEINC_HALF;
950 	    else if (value == 4) global->pageinc = PAGEINC_QUARTER;
951 	    else {
952 		config_error_ack (trace, "Page_Inc must be 1, 2, or 4\n");
953 	    }
954 	    if (DTPRINT_CONFIG) printf ("page_inc = %d\n", global->pageinc);
955 	}
956 	else if (!strcmp(cmd, "PRINT_SIZE")) {
957 	    switch (toupper(line[0])) {
958 	      case 'A':
959 		global->print_size = PRINTSIZE_A;
960 		break;
961 	      case 'B':
962 		global->print_size = PRINTSIZE_B;
963 		break;
964 	      case 'E':
965 		if (strchr (cmd, 'L'))
966 		    global->print_size = PRINTSIZE_EPSLAND;
967 		else global->print_size = PRINTSIZE_EPSPORT;
968 		break;
969 	      default:
970 		config_error_ack (trace, "Print_Size must be A, B, EPSLAND, or EPSPORT\n");
971 	    }
972 	}
973 	else if (!strcmp(cmd, "SIGNAL_HIGHLIGHT")) {
974 	    ColorNum_t color;
975 	    line += config_read_pattern (trace, line, pattern);
976 	    if (pattern[0]) {
977 		line += config_read_color (trace, line, &color, TRUE);
978 		if (color >= 0) {
979 		    sig_wildmat_select (NULL, pattern);
980 		    sig_highlight_selected (color);
981 		}
982 	    }
983 	}
984 	else if (!strcmp(cmd, "SIGNAL_NOTE")) {
985 	    char pattern2[MAXSIGLEN];
986 	    line += config_read_pattern (trace, line, pattern);
987 	    line += config_read_string (trace, line, pattern2);
988 	    if (pattern[0] && pattern2[0]) {
989 	        sig_wildmat_select (NULL, pattern);
990 	        sig_note_selected (pattern2);
991 	    }
992 	}
993 	else if (!strcmp(cmd, "SIGNAL_RADIX")) {
994 	    line += config_read_pattern (trace, line, pattern);
995 	    if (pattern[0]) {
996 		Radix_t *radix_ptr;
997 		char strg[MAXSIGLEN];
998 		line += config_read_string (trace,line, strg);
999 		radix_ptr = val_radix_find (strg);
1000 		if (radix_ptr==NULL) {
1001 		    config_error_ack (trace, "Undefined radix name\n");
1002 		} else {
1003 		    sig_wildmat_select (NULL, pattern);
1004 		    sig_radix_selected (radix_ptr	);
1005 		}
1006 	    }
1007 	}
1008 	else if (!strcmp(cmd, "SIGNAL_WAVEFORM")) {
1009 	    line += config_read_pattern (trace, line, pattern);
1010 	    if (pattern[0]) {
1011 		Waveform_t waveform = WAVEFORM_DIGITAL;
1012 		Boolean_t doit = TRUE;
1013 		char strg[MAXSIGLEN];
1014 		line += config_read_string (trace,line, strg);
1015 		if (0==strcmp (strg, "DIGITAL")) {
1016 		    waveform = WAVEFORM_DIGITAL;
1017 		} else if (0==strcmp (strg, "ANALOG")) {
1018 		    waveform = WAVEFORM_ANALOG;
1019 		} else if (0==strcmp (strg, "ANALOG_SIGNED")) {
1020 		    waveform = WAVEFORM_ANALOG_SIGNED;
1021 		} else {
1022 		    sprintf (message, "Signal_Waveform must be ANALOG or DIGITAL\n");
1023 		    config_error_ack (trace, message);
1024 		    doit = FALSE;
1025 		}
1026 		if (doit) {
1027 		    sig_wildmat_select (NULL, pattern);
1028 		    sig_waveform_selected (waveform);
1029 		}
1030 	    }
1031 	}
1032 	else if (!strcmp(cmd, "SIGNAL_ADD")) {
1033 	    char pattern2[MAXSIGLEN];
1034 	    line += config_read_pattern (trace, line, pattern);
1035 	    if (pattern[0]) {
1036 		ColorNum_t color;
1037 		line += config_read_string (trace, line, pattern2);
1038 		line += config_read_color (trace, line, &color, FALSE);
1039 		sig_wildmat_select (global->deleted_trace_head, pattern);
1040 		sig_move_selected (trace, pattern2);
1041 		if (color >= 0) {
1042 		    sig_highlight_selected (color);
1043 		}
1044 	    }
1045 	}
1046 	else if (!strcmp(cmd, "SIGNAL_MOVE")) {
1047 	    char pattern2[MAXSIGLEN];
1048 	    line += config_read_pattern (trace, line, pattern);
1049 	    if (pattern[0]) {
1050 		ColorNum_t color;
1051 		line += config_read_pattern (trace, line, pattern2);
1052 		line += config_read_color (trace, line, &color, FALSE);
1053 		sig_wildmat_select (NULL, pattern);
1054 		sig_move_selected (trace, pattern2);
1055 		if (color >= 0) {
1056 		    sig_highlight_selected (color);
1057 		}
1058 	    }
1059 	}
1060 	else if (!strcmp(cmd, "SIGNAL_RENAME")) {
1061 	    char pattern2[MAXSIGLEN];
1062 	    line += config_read_pattern (trace, line, pattern);
1063 	    line += config_read_pattern (trace, line, pattern2);
1064 	    if (pattern[0] && pattern2[0]) {
1065 		ColorNum_t color;
1066 		line += config_read_color (trace, line, &color, FALSE);
1067 		sig_wildmat_select (NULL, pattern);
1068 		sig_rename_selected (pattern2);
1069 		if (color >= 0) {
1070 		    sig_highlight_selected (color);
1071 		}
1072 	    }
1073 	}
1074 	else if (!strcmp(cmd, "SIGNAL_COPY")) {
1075 	    char pattern2[MAXSIGLEN];
1076 	    line += config_read_pattern (trace, line, pattern);
1077 	    if (pattern[0]) {
1078 		ColorNum_t color;
1079 		line += config_read_pattern (trace, line, pattern2);
1080 		line += config_read_color (trace, line, &color, FALSE);
1081 		sig_wildmat_select (NULL, pattern);
1082 		sig_copy_selected (trace, pattern2);
1083 		if (color >= 0) {
1084 		    sig_highlight_selected (color);
1085 		}
1086 	    }
1087 	}
1088 	else if (!strcmp(cmd, "SIGNAL_DELETE")) {
1089 	    line += config_read_pattern (trace, line, pattern);
1090 	    if (pattern[0]) {
1091 		sig_wildmat_select (trace, pattern);
1092 		sig_delete_selected (TRUE, FALSE);
1093 	    }
1094 	}
1095 	else if (!strcmp(cmd, "SIGNAL_DELETE_CONSTANT")) {
1096 	    char flag[MAXSIGLEN];
1097 	    Boolean_t ignorexz = FALSE;
1098 	    line += config_read_pattern (trace, line, pattern);
1099 	    if (pattern[0]) {
1100 		do {
1101 		    line += config_read_string (trace, line, flag);
1102 		    if (!strcasecmp(flag, "-IGNOREXZ")) ignorexz=TRUE;
1103 		} while (flag[0]);
1104 		sig_wildmat_select (trace, pattern);
1105 		sig_delete_selected (FALSE, ignorexz);
1106 	    }
1107 	}
1108 	else if (!strcmp(cmd, "VALUE_HIGHLIGHT")) {
1109 	    char strg[MAXSIGLEN],flag[MAXSIGLEN],signal[MAXSIGLEN]="*";
1110 	    ValSearch_t *vs_ptr;
1111 	    Boolean_t show_value=FALSE, add_cursor=FALSE;
1112 	    VSearchNum_t search_pos;
1113 	    line += config_read_value (trace, line, strg);
1114 	    line += config_read_color (trace, line, &search_pos, TRUE);
1115 	    search_pos--;
1116 	    if (search_pos >= 0) {
1117 		do {
1118 		    line += config_read_string (trace, line, flag);
1119 		    if (!strcasecmp(flag, "-CURSOR")) add_cursor=TRUE;
1120 		    else if (!strcasecmp(flag, "-VALUE")) show_value=TRUE;
1121 		    else if (flag[0]) strcpy (signal, flag);
1122 		} while (flag[0]);
1123 		/* Add it */
1124 		vs_ptr = &global->val_srch[search_pos];
1125 		vs_ptr->color = (show_value) ? search_pos+1 : 0;
1126 		vs_ptr->cursor = (add_cursor) ? search_pos+1 : 0;
1127 		string_to_value (&vs_ptr->radix, strg, &vs_ptr->value);
1128 		strcpy (vs_ptr->signal, signal);
1129 		draw_needupd_val_search ();
1130 	    }
1131 	}
1132 	else if (!strcmp(cmd, "CURSOR_ADD")) {
1133 	    ColorNum_t color;
1134 	    DTime_t ctime;
1135 	    char strg[MAXSIGLEN],flag[MAXSIGLEN];
1136 	    char note[MAXSIGLEN]="";
1137 	    CursorType_t type = CONFIG;
1138 
1139 	    line += config_read_string (trace, line, strg);
1140 	    ctime = string_to_time (trace, strg);
1141 	    line += config_read_color (trace, line, &color, TRUE);
1142 	    if (color >= 0) {
1143 		do {
1144 		    line += config_read_string (trace, line, flag);
1145 		    if (!strcasecmp(flag, "-USER")) type=USER;
1146 		    else if (!strcasecmp(flag, "-SIMVIEW") && global->simview_info_ptr) type=SIMVIEW;
1147 		    else if (flag[0]) strcpy (note, flag);
1148 		} while (flag[0]);
1149 		cur_new (ctime, color, type, note);
1150 	    }
1151 	}
1152 	else if (!strcmp(cmd, "CURSOR_STEP_FORWARD")) {
1153 	    cur_step (grid_primary_period (trace));
1154 	}
1155 	else if (!strcmp(cmd, "CURSOR_STEP_BACKWARD")) {
1156 	    cur_step ( - grid_primary_period (trace));
1157 	}
1158 	else if (!strcmp(cmd, "TIME_GOTO")) {
1159 	    DTime_t ctime;
1160 	    char strg[MAXSIGLEN];
1161 	    DTime_t end_time = global->time + (DTime_t)(( trace->width - XMARGIN - global->xstart ) / global->res);
1162 
1163 	    line += config_read_string (trace, line, strg);
1164 	    ctime = string_to_time (trace, strg);
1165 
1166 	    if ((ctime < global->time) || (ctime > end_time)) {
1167 		/* Slide time if it isn't on the screen already */
1168 		global->time = ctime - ( TIME_WIDTH (trace) /2 );
1169 		new_time (trace);
1170 	    }
1171 	}
1172 	else if (!strcmp(cmd, "RESOLUTION")) {
1173 	    DTime_t restime;
1174 	    char strg[MAXSIGLEN];
1175 
1176 	    line += config_read_string (trace, line, strg);
1177 	    restime = string_to_time (trace, strg);
1178 
1179 	    if (restime > 0) {
1180 		new_res (trace, RES_SCALE / (float)restime);
1181 	    }
1182 	}
1183 	else if (!strcmp(cmd, "SIGNAL_GOTO")) {
1184 	    line += config_read_pattern (trace, line, pattern);
1185 	    if (pattern[0]) {
1186 	        sig_goto_pattern (trace, pattern);
1187 	    }
1188 	}
1189 	else if (!strcmp(cmd, "REFRESH")) {
1190 	    draw_all_needed ();
1191 	    draw_manual_needed ();
1192 	    /* Main loop won't refresh because widget's weren't activated on socket calls */
1193 	    if (config_reading_socket) {
1194 		draw_perform();
1195 	    }
1196 	}
1197 	else if (!strcmp(cmd, "ANNOTATE")) {
1198 	    val_annotate_do_cb (NULL,trace,NULL);
1199 	}
1200 	else if (!strcmp(cmd, "START_GEOMETRY")) {
1201 	    if (*line=='"') line++;
1202 	    config_parse_geometry (line, &(global->start_geometry));
1203 	}
1204 	else if (!strcmp(cmd, "OPEN_GEOMETRY")) {
1205 	    if (*line=='"') line++;
1206 	    config_parse_geometry (line, &(global->open_geometry));
1207 	}
1208 	else if (!strcmp(cmd, "SHRINK_GEOMETRY")) {
1209 	    if (*line=='"') line++;
1210 	    config_parse_geometry (line, &(global->shrink_geometry));
1211 	}
1212 	else if (!strcmp(cmd, "SIGNAL_STATES")) {
1213 	    memset (&newsigst, 0, sizeof (SignalState_t));
1214 	    line += config_read_pattern (trace, line, newsigst.signame);
1215 	    processing_sig_state = TRUE;
1216 	    /* if (DTPRINT) printf ("config_process_states  signal=%s\n", newsigst.signame); */
1217 	    goto re_process_line;
1218 	}
1219 	else {
1220 	    sprintf (message, "Unknown command '%s'\n", cmd);
1221 	    config_error_ack (trace, message);
1222 	}
1223     }
1224 }
1225 
1226 /* Normal call */
1227 #define config_process_line(trace, line, fmt)	config_process_line_internal(trace, line, fmt, FALSE)
1228 
1229 /* EOF */
config_process_eof(Trace_t * trace)1230 static void	config_process_eof (Trace_t *trace)
1231 {
1232     char	line[3];
1233     line[0]='\0';	/* MIPS: no automatic aggregate initialization */
1234     line[1]='\0';
1235     line[2]='\0';
1236     config_process_line_internal (trace, line, FALSE, TRUE);
1237 }
1238 
1239 /**********************************************************************
1240  *	config_read_file
1241  **********************************************************************/
1242 
config_read_file(Trace_t * trace,char * filename,Boolean_t report_notfound,Boolean_t format_only)1243 void config_read_file (
1244     Trace_t	*trace,
1245     char	*filename,	/* Specific filename of CONFIG file */
1246     Boolean_t	report_notfound,
1247     Boolean_t	format_only)
1248 {
1249     FILE	*readfp;
1250     char line[1000];
1251     struct stat		newstat;	/* New status on the reread file*/
1252     int	read_fd;
1253     int		prev_cursor;
1254 
1255     if (DTPRINT_CONFIG || DTPRINT_ENTRY) printf("Reading config file %s\n", filename);
1256 
1257     if (filename[strlen(filename)-1] == '/') {
1258 	/* Ignore it, It's a directory */
1259 	return;
1260     }
1261 
1262     config_report_errors = !format_only;
1263 
1264 #ifndef VMS
1265     /* Check if regular file (not directory) */
1266     read_fd = open (filename, O_RDONLY, 0);
1267     if (read_fd>0) {
1268 	fstat (read_fd, &newstat);
1269 	if (! S_ISREG(newstat.st_mode)) {
1270 	    /* Not regular file */
1271 	    read_fd = -1;
1272 	}
1273 	close (read_fd);
1274     }
1275 #endif
1276 
1277     /* Open File For Reading */
1278     if (!(readfp=fopen(filename,"r"))) {
1279 	read_fd = -1;
1280     }
1281 
1282     if (read_fd < 0) {
1283 	if (report_notfound) {
1284 	    if (DTPRINT) printf("%%E, Can't Open File %s\n", filename);
1285 	    sprintf(message,"Can't open file %s",filename);
1286 	    dino_error_ack(trace, message);
1287 	}
1288 	return;
1289     }
1290 
1291     prev_cursor = last_set_cursor ();
1292     set_cursor (DC_BUSY);
1293 
1294     config_line_num=0;
1295     config_file = filename;
1296     config_reading_socket = FALSE;
1297     while (!feof(readfp)) {
1298 	/* Read line & kill EOL at end */
1299 	config_get_line (line, 1000, readfp);
1300 	/* 	printf ("line='%s'\n",line);	*/
1301 	config_process_line (trace, line, format_only);
1302     }
1303 
1304     config_process_eof (trace);
1305 
1306     fclose (readfp);
1307     set_cursor (prev_cursor);
1308 }
1309 
1310 /**********************************************************************
1311  *	config_read_socket
1312  **********************************************************************/
1313 
config_read_socket(char * line,char * name,int cmdnum,Boolean_t eof)1314 void config_read_socket (
1315     char	*line,
1316     char	*name,
1317     int		cmdnum,
1318     Boolean_t	eof
1319     )
1320 {
1321     config_report_errors = TRUE;
1322     config_line_num = cmdnum;
1323     config_file = name;
1324     config_reading_socket = TRUE;
1325 
1326     if (eof) {
1327 	config_process_eof (global->trace_head);
1328     }
1329     else {
1330 	config_process_line (global->trace_head, line, FALSE);
1331     }
1332 }
1333 
1334 /**********************************************************************
1335 **********************************************************************/
1336 
config_update_filenames(Trace_t * trace)1337 void config_update_filenames (Trace_t *trace)
1338 {
1339     if (DTPRINT_ENTRY) printf ("In config_update_filenames\n");
1340 
1341     global->config_filename[3][0] = '\0';
1342     global->config_filename[4][0] = '\0';
1343 
1344     /* Same directory as trace, dinotrace.dino */
1345     if (trace->dfile.filename != '\0') {
1346 	strcpy (global->config_filename[3], trace->dfile.filename);
1347 	file_directory (global->config_filename[3]);
1348 	strcat (global->config_filename[3], "dinotrace.dino");
1349     }
1350 
1351     /* Same file as trace, but .dino extension */
1352     if (trace->dfile.filename != '\0') {
1353 	char *slash;
1354 	char *pchar;
1355 	strcpy (global->config_filename[4], trace->dfile.filename);
1356 	slash = strrchr (global->config_filename[4],'/');
1357 	if (slash==NULL) slash = global->config_filename[4];
1358 	while ((pchar=strrchr(slash,'.')) != NULL) {
1359 	    *pchar = '\0';
1360 	}
1361 	strcat (global->config_filename[4], ".dino");
1362     }
1363 }
1364 
config_read_defaults(Trace_t * trace,Boolean_t format_only)1365 void config_read_defaults (
1366     Trace_t	*trace,
1367     Boolean_t	format_only)
1368 {
1369     int		cfg_num;
1370     Signal_t	*new_dispsig;
1371     Signal_t	*sig_ptr;
1372 
1373     if (DTPRINT_ENTRY) printf ("In config_read_defaults\n");
1374 
1375     new_dispsig = trace->dispsig;
1376 
1377     /* Erase old cursors */
1378     cur_delete_of_type (CONFIG);
1379 
1380     config_update_filenames(trace);
1381 
1382     for (cfg_num=0; cfg_num<MAXCFGFILES; cfg_num++) {
1383 	if ( global->config_enable[cfg_num] ) {
1384 	    config_read_file (trace, global->config_filename[cfg_num], FALSE, format_only);
1385 	}
1386     }
1387 
1388     /* If user deleted and readded signals, we might have reset */
1389     /* dispsig.  Attempt to restore */
1390     if (new_dispsig && trace->dispsig == trace->firstsig) {
1391 	for (sig_ptr = trace->firstsig; sig_ptr; sig_ptr = sig_ptr->forward) {
1392 	    if (sig_ptr == new_dispsig) {
1393 		/* Is still actively displayed (else deleted) */
1394 		trace->dispsig = new_dispsig;
1395 		vscroll_new (trace, 0);
1396 		break;
1397 	    }
1398 	}
1399 
1400     }
1401 
1402     /* Apply the statenames */
1403     grid_calc_autos (trace);
1404 
1405     draw_all_needed ();
1406     if (DTPRINT_ENTRY) printf ("Exit config_read_defaults\n");
1407 }
1408 
1409 /**********************************************************************
1410 *	config_writing
1411 **********************************************************************/
1412 
config_write_file(Trace_t * trace,char * filename)1413 void config_write_file (
1414     Trace_t	*trace,
1415     char	*filename)	/* Specific filename of CONFIG file */
1416 {
1417     FILE	*writefp;
1418     Signal_t	*sig_ptr;
1419     int		grid_num;
1420     Grid_t	*grid_ptr;
1421     int		i;
1422     char	strg[MAXSIGLEN];
1423     const char	*c;	/* Comment or null */
1424     Trace_t	*trace_top = trace;
1425 
1426     if (DTPRINT_CONFIG || DTPRINT_ENTRY) printf("Writing config file %s\n", filename);
1427 
1428     /* Open File For Writing */
1429     if (!(writefp=fopen(filename,"w"))) {
1430 	if (DTPRINT) printf("%%E, Can't Write File %s\n", filename);
1431 	sprintf(message,"Can't write file %s",filename);
1432 	dino_error_ack(trace, message);
1433 	return;
1434     }
1435 
1436     c = (global->cuswr_item[CUSWRITEM_COMMENT]) ? "#" : "";
1437 
1438     fprintf (writefp, "##### Customization Write by %s\n", DTVERSION);
1439     fprintf (writefp, "##### Created %s\n", date_string(0));
1440 
1441     if (global->cuswr_item[CUSWRITEM_PERSONAL]) {
1442         fprintf (writefp, "\n#### Global Personal Preferences ####\n");
1443 	if (DTDEBUG) {
1444 	    fprintf (writefp, "%sdebug\t\t%s\n", c, DTDEBUG?"ON":"OFF");
1445 	    /*fprintf (writefp, "%sprint\t\t%x\n", c, DTPRINT?DTPRINT:"OFF"); prints too much on reread*/
1446 	}
1447 	fprintf (writefp, "%srefreshing\t%s\n", c, global->redraw_manually?"MANUAL":"AUTO");
1448 	fprintf (writefp, "%sdraw_prefix\t%s\n", c, global->prefix_enable?"ON":"OFF");
1449 	fprintf (writefp, "%ssave_enables\t%s\n", c, global->save_enables?"ON":"OFF");
1450 	fprintf (writefp, "%ssave_ordering\t%s\n", c, global->save_ordering?"ON":"OFF");
1451 	fprintf (writefp, "%ssave_duplicates\t%s\n", c, global->save_duplicates?"ON":"OFF");
1452 	fprintf (writefp, "%sclick_to_edge\t%s\n", c, global->click_to_edge?"ON":"OFF");
1453 	fprintf (writefp, "%ssignal_height\t%d\n", c, global->sighgt);
1454 	fprintf (writefp, "%srise_fall_time\t%d\n", c, global->sigrf);
1455 	fprintf (writefp, "%stime_rep\t%s\n", c, time_units_to_string (global->timerep, TRUE));
1456 	fprintf (writefp, "%scursor\t\t%s\n", c, global->cursor_vis?"ON":"OFF");
1457 	fprintf (writefp, "%spage_inc\t%d\n", c,
1458 		 global->pageinc==PAGEINC_QUARTER ? 4 : (global->pageinc==PAGEINC_HALF?2:1) );
1459 	fprintf (writefp, "%sprint_size\t", c);
1460 	switch (global->print_size) {
1461 	  case PRINTSIZE_A:		fprintf (writefp, "A\n");	break;
1462 	  case PRINTSIZE_B:		fprintf (writefp, "B\n");	break;
1463 	  case PRINTSIZE_EPSLAND:	fprintf (writefp, "EPSLAND\n");	break;
1464 	  case PRINTSIZE_EPSPORT:	fprintf (writefp, "EPSPORT\n");	break;
1465 	}
1466 
1467 	config_geometry_string (&global->start_geometry, strg);
1468 	fprintf (writefp, "%sstart_geometry\t%s\n",c, strg);
1469 	config_geometry_string (&global->open_geometry, strg);
1470 	fprintf (writefp, "%sopen_geometry\t%s\n",c,  strg);
1471 	config_geometry_string (&global->shrink_geometry, strg);
1472 	fprintf (writefp, "%sshrink_geometry\t%s\n",c, strg);
1473 
1474 	if (global->time_format[0])
1475 	  fprintf (writefp, "%stime_format\t%s\n",c, global->time_format);
1476 
1477 	signalstate_write (writefp, c);
1478     }
1479 
1480     if (global->cuswr_item[CUSWRITEM_VALSEARCH]) {
1481 	fprintf (writefp, "\n#### Value Searches ####\n");
1482 	for (i=1; i<=MAX_SRCH; i++) {
1483 	    ValSearch_t *vs_ptr = &global->val_srch[i-1];
1484 	    char strg[MAXSIGLEN];
1485 	    if (vs_ptr->color || vs_ptr->cursor) {
1486 		val_to_string (vs_ptr->radix, strg, &vs_ptr->value, 0, FALSE, TRUE);
1487 		fprintf (writefp, "%svalue_highlight %s %d \"%s\" %s %s\n",c,
1488 			 strg, i, vs_ptr->signal,
1489 			 vs_ptr->color ? "-VALUE":"",
1490 			 vs_ptr->cursor ? "-CURSOR":"");
1491 	    }
1492 	}
1493     }
1494 
1495     if (global->cuswr_item[CUSWRITEM_CURSORS]) {
1496 	fprintf (writefp, "\n#### Cursors ####\n");
1497 	cur_write (writefp, c);
1498     }
1499 
1500     if (global->cuswr_item[CUSWRITEM_FORMAT]) {
1501 	fprintf (writefp, "\n#### Trace Format ####\n");
1502 	for (trace = global->trace_head; trace; trace = trace->next_trace) {
1503 	    if ((   global->cuswr_traces == TRACESEL_THIS && trace!=trace_top)
1504 		|| (global->cuswr_traces == TRACESEL_ALL && trace==global->deleted_trace_head)) {
1505 		continue;
1506 	    }
1507 	    if (trace->loaded) {
1508 		fprintf (writefp, "###set_trace\t%s\n", trace->dfile.filename);
1509 		fprintf (writefp, "%sfile_format\t%s\n",c, filetypes[trace->dfile.fileformat].name);
1510 		fprintf (writefp, "%svector_separator\t\"%c\"\n",c, trace->dfile.vector_separator);
1511 		fprintf (writefp, "%shierarchy_separator\t\"%c\"\n",c, trace->dfile.hierarchy_separator);
1512 		fprintf (writefp, "%stime_multiplier\t%d\n",c, global->tempest_time_mult);
1513 		fprintf (writefp, "%stime_precision\t%s\n",c, time_units_to_string (global->time_precision, TRUE));
1514 	    }
1515 	}
1516     }
1517 
1518     if (global->cuswr_item[CUSWRITEM_GRIDS]) {
1519 	fprintf (writefp, "\n#### Grids ####\n");
1520 	for (trace = global->trace_head; trace; trace = trace->next_trace) {
1521 	    if ((   global->cuswr_traces == TRACESEL_THIS && trace!=trace_top)
1522 		|| (global->cuswr_traces == TRACESEL_ALL && trace==global->deleted_trace_head)) {
1523 		continue;
1524 	    }
1525 	    if (trace->loaded) {
1526 		fprintf (writefp, "###set_trace\t%s\n", trace->dfile.filename);
1527 		for (grid_num=0; grid_num<MAXGRIDS; grid_num++) {
1528 		    grid_ptr = &(trace->grid[grid_num]);
1529 
1530 		    fprintf (writefp, "%sgrid\t\t%d\t%s\n",c, grid_num, grid_ptr->visible?"ON":"OFF");
1531 		    fprintf (writefp, "%sgrid_type\t%d\t%s\n",c, grid_num, grid_ptr->wide_line?"WIDE":"NORMAL");
1532 		    fprintf (writefp, "%sgrid_signal\t%d\t\"%s\"\n",c, grid_num, grid_ptr->signal);
1533 		    fprintf (writefp, "%sgrid_color\t%d\t%d\n",c, grid_num, grid_ptr->color);
1534 		    fprintf (writefp, "%sgrid_resolution\t%d\t",c, grid_num);
1535 		    switch (grid_ptr->period_auto) {
1536 		      case PA_AUTO:		fprintf (writefp, "ASSERTION\n");	break;
1537 		      default:		fprintf (writefp, "%d\n", grid_ptr->period);	break;
1538 		    }
1539 		    fprintf (writefp, "%sgrid_align\t%d\t",c, grid_num);
1540 		    switch (grid_ptr->align_auto) {
1541 		      case AA_ASS:		fprintf (writefp, "ASSERTION\n");	break;
1542 		      case AA_DEASS:	fprintf (writefp, "DEASSERTION\n");	break;
1543 		      default:		fprintf (writefp, "%d\n", grid_ptr->alignment);	break;
1544 		    }
1545 		}
1546 	    }
1547 	}
1548     }
1549 
1550     if (global->cuswr_item[CUSWRITEM_SIGHIGHLIGHT]) {
1551 	fprintf (writefp, "\n#### Signal Highlighting, Commenting, etc ####\n");
1552 	for (trace = global->deleted_trace_head; trace; trace = trace->next_trace) {
1553 	    if ((   global->cuswr_traces == TRACESEL_THIS && trace!=trace_top)
1554 		|| (global->cuswr_traces == TRACESEL_ALL && trace==global->deleted_trace_head)) {
1555 		continue;
1556 	    }
1557 	    fprintf (writefp, "###set_trace %s\n", trace->dfile.filename);
1558 	    /* Save signal colors */
1559 	    for (sig_ptr = trace->firstsig; sig_ptr; sig_ptr = sig_ptr->forward) {
1560 		if (sig_ptr->color && !sig_ptr->search) {
1561 		    fprintf (writefp, "%ssignal_highlight %s %d\n",c, sig_ptr->signame, sig_ptr->color);
1562 		}
1563 		if (sig_ptr->note) fprintf (writefp, "%ssignal_note %s \"%s\"\n",c, sig_ptr->signame, sig_ptr->note);
1564 		if (sig_ptr->radix != global->radixs[0]) {
1565 		    fprintf (writefp, "%ssignal_radix %s %s\n",c, sig_ptr->signame, sig_ptr->radix->name);
1566 		}
1567 	    }
1568 	}
1569     }
1570 
1571     if (global->cuswr_item[CUSWRITEM_SIGORDER]) {
1572 	fprintf (writefp, "\n#### Signal Ordering ####\n");
1573 	for (trace = global->trace_head; trace; trace = trace->next_trace) {
1574 	    if ((   global->cuswr_traces == TRACESEL_THIS && trace!=trace_top)
1575 		|| (global->cuswr_traces == TRACESEL_ALL && trace==global->deleted_trace_head)) {
1576 		continue;
1577 	    }
1578 	    fprintf (writefp, "###set_trace %s\n", trace->dfile.filename);
1579 	    fprintf (writefp, "%ssignal_delete *\n",c);
1580 	    /* Save signal colors */
1581 	    for (sig_ptr = trace->firstsig; sig_ptr; sig_ptr = sig_ptr->forward) {
1582 		fprintf (writefp, "%ssignal_add %s\n",c, sig_ptr->signame);
1583 	    }
1584 	}
1585     }
1586 
1587     fprintf (writefp, "\n\n##### Customization Write by %s\n", DTVERSION);
1588     fprintf (writefp, "##### Created %s\n", date_string(0));
1589 
1590     fclose (writefp);
1591 }
1592 
1593 /**********************************************************************
1594 *	config_restore_defaults
1595 **********************************************************************/
1596 
config_trace_defaults(Trace_t * trace)1597 void config_trace_defaults (
1598     Trace_t	*trace)
1599 {
1600     trace->dfile.hierarchy_separator = '.';
1601     trace->dfile.vector_separator = '[';
1602     trace->dfile.vectorend_separator = ']';
1603 
1604     grid_reset_cb (trace->main);
1605 }
1606 
1607 
config_global_defaults(void)1608 void config_global_defaults(void)
1609 {
1610     signalstate_free ();
1611     draw_needupd_val_states ();
1612     draw_needupd_sig_start ();
1613 
1614     global->sighgt = 15;
1615     global->pageinc = PAGEINC_FULL;
1616     global->save_ordering = TRUE;
1617     global->cursor_vis = TRUE;
1618     global->sigrf = SIG_RF;
1619     global->timerep = global->time_precision;
1620 }
1621 
1622 
1623