/* "NETGEN", a netlist-specification tool for VLSI Copyright (C) 1989, 1990 Massimo A. Sivilotti Author's address: mass@csvax.cs.caltech.edu; Caltech 256-80, Pasadena CA 91125. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation (any version). This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file copying. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* pdutils.c -- various public-domain versions of useful functions */ #include "config.h" #include #include #ifdef IBMPC #include #endif #if defined(__STDC__) || defined(IBMPC) #include #else #include #endif #include "netgen.h" /*************************************************************************/ /* */ /* Random number generators */ /* */ /*************************************************************************/ /* See NUMERICAL RECIPES IN C */ #include #define M 714025L #define IA 1366 #define IC 150889L static long idum = -1; /* needs to be initialized to avoid seg fault if 0 */ float ran2(void) { static long iy,ir[98]; static int iff=0; int j; void nrerror(); if (idum < 0 || iff == 0) { iff=1; if ((idum=(IC-(idum)) % M) < 0) idum = -idum; for (j=1;j<=97;j++) { idum=(IA*idum+IC) % M; ir[j]=idum; } idum=(IA*idum+IC) % M; iy=idum; } j=(int)(1 + 97.0*iy/M); /* the cast was added by Glenn for C++ */ if (j > 97 || j < 1) perror("RAN2: This cannot happen."); iy=ir[j]; idum=(IA*idum+IC) % M; ir[j]=idum; return (float) iy/M; } #undef M #undef IA #undef IC #if 0 int Random(int max) { int i; float f; f = ran2(); i = f * max; printf("Random(%d) computes %f, returns: %d\n", max, f, i); return(i); } #else int Random(int max) { return(ran2() * max); } #endif long RandomSeed(long seed) /* initialize idum to some negative integer */ { long oldidum; oldidum = idum; if (seed == 0) seed = -1; if (seed > 0) seed = -seed; idum = seed; return(oldidum); } float RandomUniform(void) { return(ran2()); } /*************************************************************************/ /* */ /* String manipulation routines for deficient libraries */ /* */ /*************************************************************************/ #ifdef NEED_STRSTR /* strstr - find first occurrence of wanted in s */ /* return pointer to found location, or NULL if none */ char *strstr(char *s, char *wanted) { register char *scan; register int len; register char firstc; /* deleted by Glenn -- Not necessary (and conflict with declarations in .h) extern int strcmp(); extern int strlen(); */ /* * The odd placement of the two tests is so "" is findable. * Also, we inline the first char for speed. * The ++ on scan has been moved down for optimization. */ firstc = *wanted; len = strlen(wanted); for (scan = s; *scan != firstc || strncmp(scan, wanted, len) != 0; ) if (*scan++ == '\0') return(NULL); return(scan); } #endif #ifdef NEED_STRCASECMP /* strcasecmp - compare string s1 to s2, case insensitive */ /* returns <0 for <, 0 for ==, >0 for > */ int strcasecmp(char *s1, char *s2) { register char *scan1; register char *scan2; scan1 = s1; scan2 = s2; while (*scan1 != '\0' && toupper(*scan1) == toupper(*scan2)) { scan1++; scan2++; } /* * The following case analysis is necessary so that characters * which look negative collate low against normal characters but * high against the end-of-string NUL. */ if (*scan1 == '\0' && *scan2 == '\0') return(0); else if (*scan1 == '\0') return(-1); else if (*scan2 == '\0') return(1); else return(*scan1 - *scan2); } #endif #ifdef NEED_STRING /* * char *strtok(s,delim); * * Get next token from string s (NULL on 2nd, 3rd, etc. calls), * where tokens are nonempty strings separated by runs of * chars from delim. Writes NULs into s to end tokens. delim need not * remain constant from call to call. */ static char *scanpoint = NULL; char *strtok(char *s, char *delim) { register char *scan; char *tok; register char *dscan; if (s == NULL && scanpoint == NULL) return(NULL); if (s != NULL) scan = s; else scan = scanpoint; /* * Scan leading delimiters. */ for (; *scan != '\0'; scan++) { for (dscan = delim; *dscan != '\0'; dscan++) if (*scan == *dscan) break; if (*dscan == '\0') break; } if (*scan == '\0') { scanpoint = NULL; return(NULL); } tok = scan; /* * Scan token. */ for (; *scan != '\0'; scan++) { for (dscan = delim; *dscan != '\0';) /* ++ moved down. */ if (*scan == *dscan++) { scanpoint = scan+1; *scan = '\0'; return(tok); } } /* * Reached end of string. */ scanpoint = NULL; return(tok); } /* * strcspn - find length of initial segment of s consisting entirely * of characters not from reject */ int strcspn(char *s, char *reject) { register char *scan; register char *rscan; register int count; count = 0; for (scan = s; *scan != '\0'; scan++) { for (rscan = reject; *rscan != '\0';) /* ++ moved down. */ if (*scan == *rscan++) return(count); count++; } return(count); } /* * strpbrk - find first occurrence of any char from breakat in s */ char *strpbrk(char *s, char *breakat) /* found char, or NULL if none */ { register char *sscan; register char *bscan; for (sscan = s; *sscan != '\0'; sscan++) { for (bscan = breakat; *bscan != '\0';) /* ++ moved down. */ if (*sscan == *bscan++) return(sscan); } return(NULL); } #endif #ifdef NEED_STRTOL long strtol(char *str, char **ptr, int base) /* extremely poor emulator */ { long result; int fields; if (ptr != NULL) *ptr = str; fields = sscanf(str,"%ld",&result); if (fields == 1) { if (ptr != NULL) *ptr = str+1; /* bogus, but why not */ return(result); } return(0); } #endif #ifdef NEED_VPRINTF #if 1 /* Portable vsprintf by Robert A. Larson */ /* Copyright 1989 Robert A. Larson. * Distribution in any form is allowed as long as the author * retains credit, changes are noted by their author and the * copyright message remains intact. This program comes as-is * with no warentee of fitness for any purpouse. * * Thanks to Doug Gwen, Chris Torek, and others who helped clarify * the ansi printf specs. * * Please send any bug fixes and improvments to blarson@skat.usc.edu . * The use of goto is NOT a bug. */ /* Feb 7, 1989 blarson First usenet release */ /* This code implements the vsprintf function, without relying on * the existance of _doprint or other system specific code. * * Define NOVOID if void * is not a supported type. * * Two compile options are available for efficency: * INTSPRINTF should be defined if sprintf is int and returns * the number of chacters formated. * LONGINT should be defined if sizeof(long) == sizeof(int) * * They only make the code smaller and faster, they need not be * defined. * * UNSIGNEDSPECIAL should be defined if unsigned is treated differently * than int in argument passing. If this is definded, and LONGINT is not, * the compiler must support the type unsingned long. * * Most quirks and bugs of the available sprintf fuction are duplicated, * however * in the width and precision fields will work correctly * even if sprintf does not support this, as will the n format. * * Bad format strings, or those with very long width and precision * fields (including expanded * fields) will cause undesired results. */ #ifdef OSK /* os9/68k can take advantage of both */ #define LONGINT #define INTSPRINTF #endif /* This must be a typedef not a #define! */ #ifdef NOVOID typedef char *pointer; #else typedef void *pointer; #endif #ifdef INTSPRINTF #define Sprintf(string,format,arg) (sprintf((string),(format),(arg))) #else #define Sprintf(string,format,arg) (\ sprintf((string),(format),(arg)),\ strlen(string)\ ) #endif typedef int *intp; int vsprintf(dest, format, args) char *dest; register char *format; va_list args; { register char *dp = dest; register char c; register char *tp; char tempfmt[64]; #ifndef LONGINT int longflag; #endif tempfmt[0] = '%'; while(c = *format++) { if(c=='%') { tp = &tempfmt[1]; #ifndef LONGINT longflag = 0; #endif continue_format: switch(c = *format++) { case 's': *tp++ = c; *tp = '\0'; dp += Sprintf(dp, tempfmt, va_arg(args, char *)); break; case 'u': case 'x': case 'o': case 'X': #ifdef UNSIGNEDSPECIAL *tp++ = c; *tp = '\0'; #ifndef LONGINT if(longflag) dp += Sprintf(dp, tempfmt, va_arg(args, unsigned long)); else #endif dp += Sprintf(dp, tempfmt, va_arg(args, unsigned)); break; #endif case 'd': case 'c': case 'i': *tp++ = c; *tp = '\0'; #ifndef LONGINT if(longflag) dp += Sprintf(dp, tempfmt, va_arg(args, long)); else #endif dp += Sprintf(dp, tempfmt, va_arg(args, int)); break; case 'f': case 'e': case 'E': case 'g': case 'G': *tp++ = c; *tp = '\0'; dp += Sprintf(dp, tempfmt, va_arg(args, double)); break; case 'p': *tp++ = c; *tp = '\0'; dp += Sprintf(dp, tempfmt, va_arg(args, pointer)); break; case '-': case '+': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': case ' ': case '#': case 'h': *tp++ = c; goto continue_format; case 'l': #ifndef LONGINT longflag = 1; *tp++ = c; #endif goto continue_format; case '*': tp += Sprintf(tp, "%d", va_arg(args, int)); goto continue_format; case 'n': *va_arg(args, intp) = dp - dest; break; case '%': default: *dp++ = c; break; } } else *dp++ = c; } *dp = '\0'; return dp - dest; } /* Portable vfprintf and vprintf by Robert A. Larson */ int vfprintf(dest, format, args) FILE *dest; register char *format; va_list args; { register char c; register char *tp; register int count = 0; char tempfmt[64]; #ifndef LONGINT int longflag; #endif tempfmt[0] = '%'; while(c = *format++) { if(c=='%') { tp = &tempfmt[1]; #ifndef LONGINT longflag = 0; #endif continue_format: switch(c = *format++) { case 's': *tp++ = c; *tp = '\0'; count += fprintf(dest, tempfmt, va_arg(args, char *)); break; case 'u': case 'x': case 'o': case 'X': #ifdef UNSIGNEDSPECIAL *tp++ = c; *tp = '\0'; #ifndef LONGINT if(longflag) count += fprintf(dest, tempfmt, va_arg(args, unsigned long)); else #endif count += fprintf(dest, tempfmt, va_arg(args, unsigned)); break; #endif case 'd': case 'c': case 'i': *tp++ = c; *tp = '\0'; #ifndef LONGINT if(longflag) count += fprintf(dest, tempfmt, va_arg(args, long)); else #endif count += fprintf(dest, tempfmt, va_arg(args, int)); break; case 'f': case 'e': case 'E': case 'g': case 'G': *tp++ = c; *tp = '\0'; count += fprintf(dest, tempfmt, va_arg(args, double)); break; case 'p': *tp++ = c; *tp = '\0'; count += fprintf(dest, tempfmt, va_arg(args, pointer)); break; case '-': case '+': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': case ' ': case '#': case 'h': *tp++ = c; goto continue_format; case 'l': #ifndef LONGINT longflag = 1; *tp++ = c; #endif goto continue_format; case '*': tp += Sprintf(tp, "%d", va_arg(args, int)); goto continue_format; case 'n': *va_arg(args, intp) = count; break; case '%': default: putc(c, dest); count++; break; } } else { putc(c, dest); count++; } } return count; } int vprintf(format, args) char *format; va_list args; { return vfprintf(stdout, format, args); } #else /* this code works on machines that have _doprnt (Vaxes, etc) */ int vfprintf(FILE *fp, char *fmt, va_list args) { _doprnt(fmt, args, fp); return(ferror(fp)? EOF: 0); } int vsprintf(char *str, char *fmt, va_list args) { struct _iobuf _strbuf; _strbuf._flag = _IOWRT+_IOSTRG; _strbuf._ptr = str; _strbuf._cnt = 32767; _doprnt(fmt, args, &_strbuf); putc('\0', &_strbuf); return(strlen(str)); } #endif #endif /* NEED_VPRINTF */