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