1 /* "NETGEN", a netlist-specification tool for VLSI
2    Copyright (C) 1989, 1990   Massimo A. Sivilotti
3    Author's address: mass@csvax.cs.caltech.edu;
4                      Caltech 256-80, Pasadena CA 91125.
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation (any version).
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file copying.  If not, write to
17 the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 
19 /* pdutils.c -- various public-domain versions of useful functions */
20 
21 #include "config.h"
22 
23 #include <stdio.h>
24 #include <ctype.h>
25 #ifdef IBMPC
26 #include <alloc.h>
27 #endif
28 
29 #if defined(__STDC__) || defined(IBMPC)
30 #include <stdarg.h>
31 #else
32 #include <varargs.h>
33 #endif
34 
35 #include "netgen.h"
36 
37 /*************************************************************************/
38 /*                                                                       */
39 /*    Random number generators                                           */
40 /*                                                                       */
41 /*************************************************************************/
42 
43 /* See NUMERICAL RECIPES IN C */
44 
45 #include <math.h>
46 
47 #define M 714025L
48 #define IA 1366
49 #define IC 150889L
50 
51 static long idum = -1;  /* needs to be initialized to avoid seg fault if 0 */
52 
ran2(void)53 float ran2(void)
54 {
55 	static long iy,ir[98];
56 	static int iff=0;
57 	int j;
58 	void nrerror();
59 
60 	if (idum < 0 || iff == 0) {
61 		iff=1;
62 		if ((idum=(IC-(idum)) % M) < 0) idum = -idum;
63 		for (j=1;j<=97;j++) {
64 			idum=(IA*idum+IC) % M;
65 			ir[j]=idum;
66 		}
67 		idum=(IA*idum+IC) % M;
68 		iy=idum;
69 	}
70 	j=(int)(1 + 97.0*iy/M); /* the cast was added by Glenn for C++ */
71 	if (j > 97 || j < 1) perror("RAN2: This cannot happen.");
72 	iy=ir[j];
73 	idum=(IA*idum+IC) % M;
74 	ir[j]=idum;
75 	return (float) iy/M;
76 }
77 
78 #undef M
79 #undef IA
80 #undef IC
81 
82 #if 0
83 int Random(int max)
84 {
85   int i;
86   float f;
87   f = ran2();
88   i = f * max;
89   printf("Random(%d) computes %f, returns: %d\n", max, f, i);
90   return(i);
91 }
92 #else
Random(int max)93 int Random(int max)
94 {
95   return(ran2() * max);
96 }
97 #endif
98 
RandomSeed(long seed)99 long RandomSeed(long seed)
100 /* initialize idum to some negative integer */
101 {
102 	long oldidum;
103 
104 	oldidum = idum;
105 	if (seed == 0) seed = -1;
106 	if (seed > 0) seed = -seed;
107 	idum = seed;
108 	return(oldidum);
109 }
110 
RandomUniform(void)111 float RandomUniform(void)
112 {
113 	return(ran2());
114 }
115 
116 /*************************************************************************/
117 /*                                                                       */
118 /*    String manipulation routines for deficient libraries               */
119 /*                                                                       */
120 /*************************************************************************/
121 
122 
123 #ifdef NEED_STRSTR
124 /* strstr - find first occurrence of wanted in s */
125 /* return pointer to found location, or NULL if none */
strstr(char * s,char * wanted)126 char *strstr(char *s, char *wanted)
127 {
128 	register char *scan;
129 	register int len;
130 	register char firstc;
131 /* deleted by Glenn -- Not necessary (and conflict with declarations in .h)
132 	extern int strcmp();
133 	extern int strlen();
134 */
135 
136 	/*
137 	 * The odd placement of the two tests is so "" is findable.
138 	 * Also, we inline the first char for speed.
139 	 * The ++ on scan has been moved down for optimization.
140 	 */
141 	firstc = *wanted;
142 	len = strlen(wanted);
143 	for (scan = s; *scan != firstc || strncmp(scan, wanted, len) != 0; )
144 		if (*scan++ == '\0')
145 			return(NULL);
146 	return(scan);
147 }
148 #endif
149 
150 #ifdef NEED_STRCASECMP
151 /* strcasecmp - compare string s1 to s2, case insensitive */
152 /* returns <0 for <, 0 for ==, >0 for > */
strcasecmp(char * s1,char * s2)153 int strcasecmp(char *s1, char *s2)
154 {
155 	register char *scan1;
156 	register char *scan2;
157 
158 	scan1 = s1;
159 	scan2 = s2;
160 	while (*scan1 != '\0' && toupper(*scan1) == toupper(*scan2)) {
161 		scan1++;
162 		scan2++;
163 	}
164 
165 	/*
166 	 * The following case analysis is necessary so that characters
167 	 * which look negative collate low against normal characters but
168 	 * high against the end-of-string NUL.
169 	 */
170 	if (*scan1 == '\0' && *scan2 == '\0')
171 		return(0);
172 	else if (*scan1 == '\0')
173 		return(-1);
174 	else if (*scan2 == '\0')
175 		return(1);
176 	else
177 		return(*scan1 - *scan2);
178 }
179 #endif
180 
181 #ifdef NEED_STRING
182 /*
183  * char *strtok(s,delim);
184  *
185  * Get next token from string s (NULL on 2nd, 3rd, etc. calls),
186  * where tokens are nonempty strings separated by runs of
187  * chars from delim.  Writes NULs into s to end tokens.  delim need not
188  * remain constant from call to call.
189  */
190 
191 static char *scanpoint = NULL;
192 
strtok(char * s,char * delim)193 char *strtok(char *s, char *delim)
194 {
195 	register char *scan;
196 	char *tok;
197 	register char *dscan;
198 
199 	if (s == NULL && scanpoint == NULL)
200 		return(NULL);
201 	if (s != NULL)
202 		scan = s;
203 	else
204 		scan = scanpoint;
205 
206 	/*
207 	 * Scan leading delimiters.
208 	 */
209 	for (; *scan != '\0'; scan++) {
210 		for (dscan = delim; *dscan != '\0'; dscan++)
211 			if (*scan == *dscan)
212 				break;
213 		if (*dscan == '\0')
214 			break;
215 	}
216 	if (*scan == '\0') {
217 		scanpoint = NULL;
218 		return(NULL);
219 	}
220 
221 	tok = scan;
222 
223 	/*
224 	 * Scan token.
225 	 */
226 	for (; *scan != '\0'; scan++) {
227 		for (dscan = delim; *dscan != '\0';)	/* ++ moved down. */
228 			if (*scan == *dscan++) {
229 				scanpoint = scan+1;
230 				*scan = '\0';
231 				return(tok);
232 			}
233 	}
234 
235 	/*
236 	 * Reached end of string.
237 	 */
238 	scanpoint = NULL;
239 	return(tok);
240 }
241 
242 
243 
244 /*
245  * strcspn - find length of initial segment of s consisting entirely
246  * of characters not from reject
247  */
248 
strcspn(char * s,char * reject)249 int strcspn(char *s, char *reject)
250 {
251 	register char *scan;
252 	register char *rscan;
253 	register int count;
254 
255 	count = 0;
256 	for (scan = s; *scan != '\0'; scan++) {
257 		for (rscan = reject; *rscan != '\0';)	/* ++ moved down. */
258 			if (*scan == *rscan++)
259 				return(count);
260 		count++;
261 	}
262 	return(count);
263 }
264 
265 
266 /*
267  * strpbrk - find first occurrence of any char from breakat in s
268  */
269 
270 
strpbrk(char * s,char * breakat)271 char *strpbrk(char *s, char *breakat)
272 /* found char, or NULL if none */
273 {
274 	register char *sscan;
275 	register char *bscan;
276 
277 	for (sscan = s; *sscan != '\0'; sscan++) {
278 		for (bscan = breakat; *bscan != '\0';)	/* ++ moved down. */
279 			if (*sscan == *bscan++)
280 				return(sscan);
281 	}
282 	return(NULL);
283 }
284 
285 #endif
286 
287 #ifdef NEED_STRTOL
strtol(char * str,char ** ptr,int base)288 long strtol(char *str, char **ptr, int base)
289 /* extremely poor emulator */
290 {
291   long result;
292   int fields;
293 
294   if (ptr != NULL) *ptr = str;
295   fields = sscanf(str,"%ld",&result);
296   if (fields == 1) {
297     if (ptr != NULL) *ptr = str+1;  /* bogus, but why not */
298     return(result);
299   }
300   return(0);
301 }
302 #endif
303 
304 #ifdef NEED_VPRINTF
305 
306 #if 1
307 
308 /* Portable vsprintf  by Robert A. Larson <blarson@skat.usc.edu> */
309 
310 /* Copyright 1989 Robert A. Larson.
311  * Distribution in any form is allowed as long as the author
312  * retains credit, changes are noted by their author and the
313  * copyright message remains intact.  This program comes as-is
314  * with no warentee of fitness for any purpouse.
315  *
316  * Thanks to Doug Gwen, Chris Torek, and others who helped clarify
317  * the ansi printf specs.
318  *
319  * Please send any bug fixes and improvments to blarson@skat.usc.edu .
320  * The use of goto is NOT a bug.
321  */
322 
323 /* Feb	7, 1989		blarson		First usenet release */
324 
325 /* This code implements the vsprintf function, without relying on
326  * the existance of _doprint or other system specific code.
327  *
328  * Define NOVOID if void * is not a supported type.
329  *
330  * Two compile options are available for efficency:
331  *	INTSPRINTF	should be defined if sprintf is int and returns
332  *			the number of chacters formated.
333  *	LONGINT		should be defined if sizeof(long) == sizeof(int)
334  *
335  *	They only make the code smaller and faster, they need not be
336  *	defined.
337  *
338  * UNSIGNEDSPECIAL should be defined if unsigned is treated differently
339  * than int in argument passing.  If this is definded, and LONGINT is not,
340  * the compiler must support the type unsingned long.
341  *
342  * Most quirks and bugs of the available sprintf fuction are duplicated,
343  * however * in the width and precision fields will work correctly
344  * even if sprintf does not support this, as will the n format.
345  *
346  * Bad format strings, or those with very long width and precision
347  * fields (including expanded * fields) will cause undesired results.
348  */
349 
350 #ifdef OSK		/* os9/68k can take advantage of both */
351 #define LONGINT
352 #define INTSPRINTF
353 #endif
354 
355 /* This must be a typedef not a #define! */
356 #ifdef NOVOID
357 typedef char *pointer;
358 #else
359 typedef void *pointer;
360 #endif
361 
362 #ifdef	INTSPRINTF
363 #define Sprintf(string,format,arg)	(sprintf((string),(format),(arg)))
364 #else
365 #define Sprintf(string,format,arg)	(\
366 	sprintf((string),(format),(arg)),\
367 	strlen(string)\
368 )
369 #endif
370 
371 typedef int *intp;
372 
vsprintf(dest,format,args)373 int vsprintf(dest, format, args)
374 char *dest;
375 register char *format;
376 va_list args;
377 {
378   register char *dp = dest;
379   register char c;
380   register char *tp;
381   char tempfmt[64];
382 #ifndef LONGINT
383   int longflag;
384 #endif
385 
386   tempfmt[0] = '%';
387   while(c = *format++) {
388     if(c=='%') {
389       tp = &tempfmt[1];
390 #ifndef LONGINT
391       longflag = 0;
392 #endif
393     continue_format:
394       switch(c = *format++) {
395       case 's':
396 	*tp++ = c;
397 	*tp = '\0';
398 	dp += Sprintf(dp, tempfmt, va_arg(args, char *));
399 	break;
400       case 'u':
401       case 'x':
402       case 'o':
403       case 'X':
404 #ifdef UNSIGNEDSPECIAL
405 	*tp++ = c;
406 	*tp = '\0';
407 #ifndef LONGINT
408 	if(longflag)
409 	  dp += Sprintf(dp, tempfmt, va_arg(args, unsigned long));
410 	else
411 #endif
412 	  dp += Sprintf(dp, tempfmt, va_arg(args, unsigned));
413 	break;
414 #endif
415       case 'd':
416       case 'c':
417       case 'i':
418 	*tp++ = c;
419 	*tp = '\0';
420 #ifndef LONGINT
421 	if(longflag)
422 	  dp += Sprintf(dp, tempfmt, va_arg(args, long));
423 	else
424 #endif
425 	  dp += Sprintf(dp, tempfmt, va_arg(args, int));
426 	break;
427       case 'f':
428       case 'e':
429       case 'E':
430       case 'g':
431       case 'G':
432 	*tp++ = c;
433 	*tp = '\0';
434 	dp += Sprintf(dp, tempfmt, va_arg(args, double));
435 	break;
436       case 'p':
437 	*tp++ = c;
438 	*tp = '\0';
439 	dp += Sprintf(dp, tempfmt, va_arg(args, pointer));
440 	break;
441       case '-':
442       case '+':
443       case '0':
444       case '1':
445       case '2':
446       case '3':
447       case '4':
448       case '5':
449       case '6':
450       case '7':
451       case '8':
452       case '9':
453       case '.':
454       case ' ':
455       case '#':
456       case 'h':
457 	*tp++ = c;
458 	goto continue_format;
459       case 'l':
460 #ifndef LONGINT
461 	longflag = 1;
462 	*tp++ = c;
463 #endif
464 	goto continue_format;
465       case '*':
466 	tp += Sprintf(tp, "%d", va_arg(args, int));
467 	goto continue_format;
468       case 'n':
469 	*va_arg(args, intp) = dp - dest;
470 	break;
471       case '%':
472       default:
473 	*dp++ = c;
474 	break;
475       }
476     } else *dp++ = c;
477   }
478   *dp = '\0';
479   return dp - dest;
480 }
481 
482 /* Portable vfprintf and vprintf by Robert A. Larson <blarson@skat.usc.edu> */
483 
vfprintf(dest,format,args)484 int vfprintf(dest, format, args)
485 FILE *dest;
486 register char *format;
487 va_list args;
488 {
489   register char c;
490   register char *tp;
491   register int count = 0;
492   char tempfmt[64];
493 #ifndef LONGINT
494   int longflag;
495 #endif
496 
497   tempfmt[0] = '%';
498   while(c = *format++) {
499     if(c=='%') {
500       tp = &tempfmt[1];
501 #ifndef LONGINT
502       longflag = 0;
503 #endif
504     continue_format:
505       switch(c = *format++) {
506       case 's':
507 	*tp++ = c;
508 	*tp = '\0';
509 	count += fprintf(dest, tempfmt, va_arg(args, char *));
510 	break;
511       case 'u':
512       case 'x':
513       case 'o':
514       case 'X':
515 #ifdef UNSIGNEDSPECIAL
516 	*tp++ = c;
517 	*tp = '\0';
518 #ifndef LONGINT
519 	if(longflag)
520 	  count += fprintf(dest, tempfmt, va_arg(args, unsigned long));
521 	else
522 #endif
523 	  count += fprintf(dest, tempfmt, va_arg(args, unsigned));
524 	break;
525 #endif
526       case 'd':
527       case 'c':
528       case 'i':
529 	*tp++ = c;
530 	*tp = '\0';
531 #ifndef LONGINT
532 	if(longflag)
533 	  count += fprintf(dest, tempfmt, va_arg(args, long));
534 	else
535 #endif
536 	  count += fprintf(dest, tempfmt, va_arg(args, int));
537 	break;
538       case 'f':
539       case 'e':
540       case 'E':
541       case 'g':
542       case 'G':
543 	*tp++ = c;
544 	*tp = '\0';
545 	count += fprintf(dest, tempfmt, va_arg(args, double));
546 	break;
547       case 'p':
548 	*tp++ = c;
549 	*tp = '\0';
550 	count += fprintf(dest, tempfmt, va_arg(args, pointer));
551 	break;
552       case '-':
553       case '+':
554       case '0':
555       case '1':
556       case '2':
557       case '3':
558       case '4':
559       case '5':
560       case '6':
561       case '7':
562       case '8':
563       case '9':
564       case '.':
565       case ' ':
566       case '#':
567       case 'h':
568 	*tp++ = c;
569 	goto continue_format;
570       case 'l':
571 #ifndef LONGINT
572 	longflag = 1;
573 	*tp++ = c;
574 #endif
575 	goto continue_format;
576       case '*':
577 	tp += Sprintf(tp, "%d", va_arg(args, int));
578 	goto continue_format;
579       case 'n':
580 	*va_arg(args, intp) = count;
581 	break;
582       case '%':
583       default:
584 	putc(c, dest);
585 	count++;
586 	break;
587       }
588     } else {
589       putc(c, dest);
590       count++;
591     }
592   }
593   return count;
594 }
595 
vprintf(format,args)596 int vprintf(format, args)
597 char *format;
598 va_list args;
599 {
600     return vfprintf(stdout, format, args);
601 }
602 
603 
604 #else
605 /* this code works on machines that have _doprnt (Vaxes, etc) */
606 
vfprintf(FILE * fp,char * fmt,va_list args)607 int vfprintf(FILE *fp, char *fmt, va_list args)
608 {
609 	_doprnt(fmt, args, fp);
610 	return(ferror(fp)? EOF: 0);
611 }
612 
vsprintf(char * str,char * fmt,va_list args)613 int vsprintf(char *str, char *fmt, va_list args)
614 {
615 	struct _iobuf _strbuf;
616 
617 	_strbuf._flag = _IOWRT+_IOSTRG;
618 	_strbuf._ptr = str;
619 	_strbuf._cnt = 32767;
620 	_doprnt(fmt, args, &_strbuf);
621 	putc('\0', &_strbuf);
622 	return(strlen(str));
623 }
624 #endif
625 #endif  /* NEED_VPRINTF */
626