/* * OpenPBS (Portable Batch System) v2.3 Software License * * Copyright (c) 1999-2000 Veridian Information Solutions, Inc. * All rights reserved. * * --------------------------------------------------------------------------- * For a license to use or redistribute the OpenPBS software under conditions * other than those described below, or to purchase support for this software, * please contact Veridian Systems, PBS Products Department ("Licensor") at: * * www.OpenPBS.org +1 650 967-4675 sales@OpenPBS.org * 877 902-4PBS (US toll-free) * --------------------------------------------------------------------------- * * This license covers use of the OpenPBS v2.3 software (the "Software") at * your site or location, and, for certain users, redistribution of the * Software to other sites and locations. Use and redistribution of * OpenPBS v2.3 in source and binary forms, with or without modification, * are permitted provided that all of the following conditions are met. * After December 31, 2001, only conditions 3-6 must be met: * * 1. Commercial and/or non-commercial use of the Software is permitted * provided a current software registration is on file at www.OpenPBS.org. * If use of this software contributes to a publication, product, or * service, proper attribution must be given; see www.OpenPBS.org/credit.html * * 2. Redistribution in any form is only permitted for non-commercial, * non-profit purposes. There can be no charge for the Software or any * software incorporating the Software. Further, there can be no * expectation of revenue generated as a consequence of redistributing * the Software. * * 3. Any Redistribution of source code must retain the above copyright notice * and the acknowledgment contained in paragraph 6, this list of conditions * and the disclaimer contained in paragraph 7. * * 4. Any Redistribution in binary form must reproduce the above copyright * notice and the acknowledgment contained in paragraph 6, this list of * conditions and the disclaimer contained in paragraph 7 in the * documentation and/or other materials provided with the distribution. * * 5. Redistributions in any form must be accompanied by information on how to * obtain complete source code for the OpenPBS software and any * modifications and/or additions to the OpenPBS software. The source code * must either be included in the distribution or be available for no more * than the cost of distribution plus a nominal fee, and all modifications * and additions to the Software must be freely redistributable by any party * (including Licensor) without restriction. * * 6. All advertising materials mentioning features or use of the Software must * display the following acknowledgment: * * "This product includes software developed by NASA Ames Research Center, * Lawrence Livermore National Laboratory, and Veridian Information * Solutions, Inc. * Visit www.OpenPBS.org for OpenPBS software support, * products, and information." * * 7. DISCLAIMER OF WARRANTY * * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT * ARE EXPRESSLY DISCLAIMED. * * IN NO EVENT SHALL VERIDIAN CORPORATION, ITS AFFILIATED COMPANIES, OR THE * U.S. GOVERNMENT OR ANY OF ITS AGENCIES BE LIABLE FOR ANY DIRECT OR INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This license will be governed by the laws of the Commonwealth of Virginia, * without reference to its choice of law rules. */ #include /* the master config generated by configure */ #ifndef _POSIX_SOURCE #define _POSIX_SOURCE 1 #endif /* System headers */ #include #include #include #include /* #include */ #include #include #include #include #include /* local headers */ #include "portability.h" #include "af.h" #include "pbs_error.h" /* Macros */ #define MAXDARRAY 11 /* maximum # of dynamic arrays. Must be a */ /* prime # since this is used as a hash mod */ /* value */ /* TODO: this is not a fixed number. It */ /* must be calculated. */ /* So far, slots for varstr, AllNodes, */ /* AllResmoms, Servers, Ques, as well as */ /* 5 more for each AllNodes, 1 for each */ /* server, as well as Res too! */ /* File Scope Variables */ static char ident[] = "@(#) $RCSfile$ $Revision$"; struct dynamic_array { void *ptr; /* pointer to the dynamic array */ int numElems; /* number of elements in the array */ }; static struct dynamic_array d_array[MAXDARRAY]; static char *dayofweekVal[] = { /* 0 */ "SUN", /* 1 */ "MON", /* 2 */ "TUE", /* 3 */ "WED", /* 4 */ "THU", /* 5 */ "FRI", /* 6 */ "SAT", }; #define NUMDAYOFWEEK 7 static char *actVal[] = { /* 0 */ "SYNCRUN", /* 1 */ "ASYNCRUN", /* 2 */ "DELETE", /* 3 */ "RERUN", /* 4 */ "HOLD", /* 5 */ "RELEASE", /* 6 */ "SIGNAL", /* 7 */ "MODIFYATTR", /* 8 */ "MODIFYRES", }; #define NUMACTS 9 static char *cprVal[] = { /* 0 */ "OP_EQ", /* 1 */ "OP_NEQ", /* 2 */ "OP_GT", /* 3 */ "OP_GE", /* 4 */ "OP_LT", /* 5 */ "OP_LE", /* 6 */ "OP_MAX", /* 7 */ "OP_MIN", /* ************************************************************************* */ /* Structures for the varstr */ /* ************************************************************************* */ }; #define NUMCPRS 8 struct varstr_type { void *ptr; /* ptr to malloc-ed storage of variable str */ int scope; /* variable's scope */ void *pptr; /* variable's parent ptr - useful for */ /* collectively freeing up malloc-ed storage */ /* linked to some main structure */ struct varstr_type *link; }; #define A ( (sqrt(5) - 1)/2 ) #define VARSTRLEN 500 static struct varstr_type *varstr[VARSTRLEN]; struct varstrIndex_type { struct varstr_type *mptr; struct varstrIndex_type *link; }; #define VARSTR_INDEX_LEN 480 static struct varstrIndex_type *varstrIndex[VARSTR_INDEX_LEN]; struct varstrSubIndex_type { struct varstrIndex_type *ptr; struct varstrSubIndex_type *link; }; #define VARSTR_SUBINDEX_LEN 19 static struct varstrSubIndex_type *varstrSubIndex[VARSTR_SUBINDEX_LEN]; /* ************************************************************************* */ /* Structures for the mallocTable */ /* ************************************************************************* */ struct malloc_type { int scope; /* variable's scope */ void *pptr; /* variable's parent ptr - useful for */ /* collectively freeing up malloc-ed storage */ /* linked to some main structure */ void *ptr; /* ptr to malloc-ed storage of variable str */ struct malloc_type *link; }; #define MALLOCLEN 500 static struct malloc_type *mallocTable[MALLOCLEN]; struct mallocIndex_type { struct malloc_type *mptr; struct mallocIndex_type *link; }; #define MALLOC_INDEX_LEN 480 static struct mallocIndex_type *mallocIndexTable[MALLOC_INDEX_LEN]; struct mallocSubIndex_type { struct mallocIndex_type *ptr; struct mallocSubIndex_type *link; }; #define MALLOC_SUBINDEX_LEN 19 static struct mallocSubIndex_type *mallocSubIndexTable[MALLOC_SUBINDEX_LEN]; /* ************************************************************************* */ /* Various Hash Functions */ /* ************************************************************************* */ static int varstrHash(unsigned long k) { double val; val = k * A; return(floor(VARSTRLEN*(val - floor(val)))); } static int varstrIndexHash(unsigned long k) { double val; val = k * A; return(floor(VARSTR_INDEX_LEN*(val - floor(val)))); } static int varstrSubIndexHash(unsigned long k) { return(k % VARSTR_SUBINDEX_LEN); } static int mallocTableHash(unsigned long k) { double val; val = k * A; return(floor(MALLOCLEN*(val - floor(val)))); } static int mallocIndexTableHash(unsigned long k) { double val; val = k * A; return(floor(MALLOC_INDEX_LEN*(val - floor(val)))); } static int mallocSubIndexTableHash(unsigned long k) { return(k % MALLOC_SUBINDEX_LEN); } /* Global variables */ /* External Variables */ /* External Functions */ /* Structures and Unions */ /* Signal catching functions */ /* External Functions */ /* Functions */ /* varstrSubIndex is hashed by scope */ static void varstrSubIndexAdd(struct varstrIndex_type *ptr) { struct varstrSubIndex_type *elem; int index; index = varstrSubIndexHash(ptr->mptr->scope); elem = (struct varstrSubIndex_type *) \ malloc((size_t)sizeof(struct varstrSubIndex_type)); elem->ptr = ptr; elem->link = varstrSubIndex[index]; varstrSubIndex[index] = elem; } static void varstrSubIndexFree(struct varstrIndex_type *ptr) { int index; struct varstrSubIndex_type *v, *v_before; index = varstrSubIndexHash(ptr->mptr->scope); v_before = NULL; for (v = varstrSubIndex[index]; v; v = v->link) { if (v->ptr == ptr) { if (v_before == NULL) { varstrSubIndex[index] = v->link; } else { v_before->link = v->link; } free(v); return; } v_before = v; } } /* varstrIndex is hashed by pptr */ static void varstrIndexAdd(struct varstr_type *mptr) { struct varstrIndex_type *elem; int index; index = varstrIndexHash(mptr->pptr); elem = (struct varstrIndex_type *) \ malloc((size_t)sizeof(struct varstrIndex_type)); elem->mptr = mptr; elem->link = varstrIndex[index]; varstrIndex[index] = elem; varstrSubIndexAdd(elem); } static void varstrIndexFree(struct varstr_type *mptr) { int index; struct varstrIndex_type *v, *v_before; index = varstrIndexHash(mptr->pptr); v_before = NULL; for (v = varstrIndex[index]; v; v = v->link) { if (v->mptr == mptr) { if (v_before == NULL) { varstrIndex[index] = v->link; } else { v_before->link = v->link; } varstrSubIndexFree(v); free(v); return; } v_before = v; } } static void varstrIndexFreeNoIndex(struct varstr_type *mptr) { int index; struct varstrIndex_type *v; index = varstrIndexHash(mptr->pptr); for (v = varstrIndex[index]; v; v = v->link) { if (v->mptr == mptr) { varstrSubIndexFree(v); return; } } } static void varstrIndexFreeNoSubIndex(struct varstr_type *mptr) { int index; struct varstrIndex_type *v, *v_before; index = varstrIndexHash(mptr->pptr); v_before = NULL; for (v = varstrIndex[index]; v; v = v->link) { if (v->mptr == mptr) { if (v_before == NULL) { varstrIndex[index] = v->link; } else { v_before->link = v->link; } free(v); return; } v_before = v; } } /* Adds a unique variable (ptr, scope) */ void varstrAdd(void *ptr, int scope, void *pptr) { struct varstr_type *v_elem; int index; index = varstrHash(ptr); v_elem = (struct varstr_type *) \ malloc((size_t)sizeof(struct varstr_type)); v_elem->ptr = ptr; v_elem->pptr = pptr; v_elem->scope = scope; v_elem->link = varstr[index]; varstr[index] = v_elem; varstrIndexAdd(v_elem); } void varstrRemove(void *ptr) { int index; struct varstr_type *v, *v_before; index = varstrHash(ptr); v_before = NULL; for (v = varstr[index]; v; v = v->link) { if (v->ptr == ptr) { if (v_before == NULL) { varstr[index] = v->link; } else { v_before->link = v->link; } varstrIndexFree(v); free(v); return; } v_before = v; } } /* Modifies the variable (ptr, scope) to have a 'newscope'. */ void varstrModScope(void *ptr, int newscope) { int index, index2; struct varstr_type *v; struct varstrIndex_type *v2; struct varstrIndex_type *index_entry; index = varstrHash(ptr); index_entry = NULL; for (v = varstr[index]; v; v = v->link) { if (v->ptr == ptr) { /* hash lookup against index2 */ index2 = varstrIndexHash(v->pptr); for (v2 = varstrIndex[index2]; v2; v2 = v2->link) { if (v2->mptr == v) { /* hash lookup against scope */ varstrSubIndexFree(v2); index_entry = v2; break; } } v->scope = newscope; if (index_entry != NULL) { varstrSubIndexAdd(index_entry); } return; } } } /* Modifies the variable (ptr, pptr) to have a 'newpptr'. */ void varstrModPptr(void *ptr, void *newpptr) { int index; struct varstr_type *v; index = varstrHash(ptr); for (v = varstr[index]; v; v = v->link) { if (v->ptr == ptr) { varstrIndexFree(v); v->pptr = newpptr; varstrIndexAdd(v); return; } } } /* Returns 1 if 'ptr' is an already malloc-ed variable string ; 0 otherwise. */ int inVarstr(void *ptr) { int index; struct varstr_type *v; index = varstrHash(ptr); for (v = varstr[index]; v; v = v->link) { if (v->ptr == ptr) { return(1); } } return(0); } void varstrInit(void) { int i; for (i = 0; i < VARSTRLEN; i++) { varstr[i] = (struct varstr_type *)NULL; } for (i = 0; i < VARSTR_INDEX_LEN; i++) { varstrIndex[i] = (struct varstrIndex_type *)NULL; } for (i = 0; i < VARSTR_SUBINDEX_LEN; i++) { varstrSubIndex[i] = (struct varstrSubIndex_type *)NULL; } } void varstrPrint(void) { int i; struct varstr_type *v; struct varstrIndex_type *v2; struct varstrSubIndex_type *v3; for (i = 0; i < VARSTRLEN; i++) { printf("varstr[%d]: ======================================\n", i); for (v = varstr[i]; v; v = v->link) { printf("%d:%x: (%x=%s, %d, %x)\n", i, v, v->ptr, v->ptr ? v->ptr : "null", v->scope, v->pptr); } } for (i = 0; i < VARSTR_INDEX_LEN; i++) { printf("varstrIndex[%d]: ==================================\n", i); for (v2 = varstrIndex[i]; v2; v2 = v2->link) { printf("%d:%x: (mptr: %x, hashkey-pptr: %x)\n", i, v2, v2->mptr, v2->mptr->pptr); } } for (i = 0; i < VARSTR_SUBINDEX_LEN; i++) { printf("varstrSubIndex[%d]: ===============================\n", i); for (v3 = varstrSubIndex[i]; v3; v3 = v3->link) { printf("%d:%x: (%x, hashkey-scope: %d)\n", i, v3, v3->ptr, v3->ptr->mptr->scope); } } } void varstrFree(void *ptr) { int index; struct varstr_type *v, *v_before; index = varstrHash(ptr); v_before = NULL; for (v = varstr[index]; v; v = v->link) { if (v->ptr == ptr) { free(ptr); if (v_before == NULL) { varstr[index] = v->link; } else { v_before->link = v->link; } varstrIndexFree(v); free(v); return; } v_before = v; } } static void varstrFreeNoIndex(void *ptr) { int index; struct varstr_type *v, *v_before; index = varstrHash(ptr); v_before = NULL; for (v = varstr[index]; v; v = v->link) { if (v->ptr == ptr) { free(ptr); if (v_before == NULL) { varstr[index] = v->link; } else { v_before->link = v->link; } varstrIndexFreeNoIndex(v); free(v); return; } v_before = v; } } static void varstrFreeNoSubIndex(void *ptr) { int index; struct varstr_type *v, *v_before; index = varstrHash(ptr); v_before = NULL; for (v = varstr[index]; v; v = v->link) { if (v->ptr == ptr) { free(ptr); if (v_before == NULL) { varstr[index] = v->link; } else { v_before->link = v->link; } varstrIndexFreeNoSubIndex(v); free(v); return; } v_before = v; } } /* Like varstrFree but this can be given 2 ptrs at the same time to free up */ /* This is an optomization attempt */ static void varstr2Free(void *ptr, void *ptr2) { varstrFree(ptr); varstrFree(ptr2); } void varstrFreeByScope(int scope) { int index; struct varstrSubIndex_type *v, *v_before, *linkptr; index = varstrSubIndexHash(scope); v_before = NULL; v = varstrSubIndex[index]; while (v) { linkptr = v->link; if (v->ptr->mptr->scope == scope) { varstrFreeNoSubIndex(v->ptr->mptr->ptr); if (v_before == NULL) { varstrSubIndex[index] = linkptr; } else { v_before->link = linkptr; } free(v); } else { v_before = v; } v = linkptr; } } void varstrFreeByPptr(void *pptr) { int index; struct varstrIndex_type *v, *v_before, *linkptr; index = varstrIndexHash(pptr); v_before = NULL; v = varstrIndex[index]; while (v) { linkptr = v->link; if (v->mptr->pptr == pptr) { varstrFreeNoIndex(v->mptr->ptr); if (v_before == NULL) { varstrIndex[index] = linkptr; } else { v_before->link = linkptr; } free(v); } else { v_before = v; } v = linkptr; } } /* dynamic_strcpy: almost like strdup except it can shrink or grow existing */ /* strings. For creating new strings, be sure str1_ptr is */ /* initially set to NULL! */ /* NOTE: This will update varstr to that lists pointers to all malloc-ed */ void dynamic_strcpy(char **str1_ptr, const char *str2) { char *str1_before; if (str2 == NULLSTR) { varstrFree(*str1_ptr); /* free up existing storage */ *str1_ptr = NULLSTR; return; } str1_before = *str1_ptr; if (*str1_ptr == NULLSTR) *str1_ptr = (char *) malloc((size_t) strlen(str2) + 1); else *str1_ptr = (char *) realloc((char *) * str1_ptr, (size_t) strlen(str2) + 1); assert(*str1_ptr != NULLSTR); if (str1_before != *str1_ptr) { varstrRemove(str1_before); varstrAdd(*str1_ptr, 0, (void *)NULL); /* global scope by default */ } (void)strcpy(*str1_ptr, str2); } /* dynamic_strcat: almost like strcat except '*str1_ptr' is a malloc-ed string that will be adjusted according to the size of str2 */ /* 'str1_ptr' cannot be NULL */ void dynamic_strcat(char **str1_ptr, const char *str2) { char *str1_before; int str1_len; if (str2 == NULLSTR) { return; /* just return, nothing to append to */ } if (*str1_ptr != NULLSTR) str1_len = strlen(*str1_ptr); else str1_len = 0; str1_before = *str1_ptr; if (*str1_ptr == NULLSTR) *str1_ptr = (char *) malloc((size_t) str1_len + strlen(str2) + 1); else *str1_ptr = (char *) realloc(*str1_ptr, (size_t) str1_len + strlen(str2) + 1); assert(*str1_ptr != NULLSTR); if (str1_before == NULLSTR) { **str1_ptr = '\0'; } if (str1_before != *str1_ptr) { varstrRemove(str1_before); varstrAdd(*str1_ptr, 0, (void *)NULL); /* global scope by default */ } (void)strcat(*str1_ptr, str2); } /* strToInt: given a valid string integer (containing only digit chars), returns the integer value. NOTE: if conversion is unsucessful, a value of -1 will always be returned. */ int strToInt(char *str) { long int newval; char *endp; if (str == NULLSTR) { return(-1); } newval = strtol(str, &endp, 10); if (str == endp || *endp != '\0') return(-1); return((int)newval); } /* strToFloat: given a string containing a float, return the float value. A value of 0.0 is returned if conversion failed. */ double strToFloat(char *str) { double f; char *endp; if (str == NULLSTR) { return(0.0); }; f = strtod(str, &endp); if (str == endp || *endp != '\0') { return(0.0); } return(f); } /* Returns the Dayofweek (int) given a string. This returns -1 if if conversion was unsuccessful. */ int strToDayofweek(char *str) { if (str == NULLSTR) { return(-1); } if (strncmp(str, "SUN", 3) == 0) return(SUN); else if (strncmp(str, "MON", 3) == 0) return(MON); else if (strncmp(str, "TUE", 3) == 0) return(TUE); else if (strncmp(str, "WED", 3) == 0) return(WED); else if (strncmp(str, "THU", 3) == 0) return(THU); else if (strncmp(str, "FRI", 3) == 0) return(FRI); else if (strncmp(str, "SAT", 3) == 0) return(SAT); else return(-1); } /* Gets the Date portion of the string with the form "(m|d|y@h:m:s)" or "(m|d|y)". If conversion failed, {0, 0, 0} will be returned. */ Date strToDate(str) char *str; { char *s1 = NULLSTR; /* a new string */ char *monstr; char *daystr; char *yearstr; int mon; int day; int year; char *tmp; Date date = {0, 0, 0}; if (str == NULLSTR) { return(date); } /* make copies of the string */ dynamic_strcpy(&s1, str); monstr = strchr(s1, '('); if (monstr == NULLSTR) { varstrFree(s1); return(date); } monstr++; daystr = strchr(monstr, '|'); if (daystr == NULLSTR) { varstrFree(s1); return(date); } *daystr = '\0'; daystr++; yearstr = strchr(daystr, '|'); if (yearstr == NULLSTR) { varstrFree(s1); return(date); } *yearstr = '\0'; yearstr++; tmp = strchr(yearstr, '@'); if (tmp == NULLSTR) { tmp = strchr(yearstr, ')'); if (tmp == NULLSTR) { varstrFree(s1); return(date); } } *tmp = '\0'; mon = strToInt(monstr); day = strToInt(daystr); year = strToInt(yearstr); if (mon == -1 || day == -1 || year == -1) { varstrFree(s1); return(date); } date.m = mon; date.d = day; date.y = year; varstrFree(s1); return(date); } /* Gets the Time portion of the string with the form "(m|d|y@h:m:s)" or "(h:m:s)"If conversion failed, {-1, -1, -1} will be returned. */ Time strToTime(str) char *str; { char *s1 = NULLSTR; /* a new string */ char *hhstr; char *mmstr; char *ssstr; int hh; int mm; int ss; char *tmp; Time time = { -1, -1, -1}; if (str == NULLSTR) { return(time); } /* make copies of the string */ dynamic_strcpy(&s1, str); hhstr = strchr(s1, '@'); if (hhstr == NULLSTR) { hhstr = strchr(s1, '('); if (hhstr == NULLSTR) { varstrFree(s1); return(time); } } hhstr++; mmstr = strchr(hhstr, ':'); if (mmstr == NULLSTR) { varstrFree(s1); return(time); } *mmstr = '\0'; mmstr++; ssstr = strchr(mmstr, ':'); if (ssstr == NULLSTR) { varstrFree(s1); return(time); } *ssstr = '\0'; ssstr++; tmp = strchr(ssstr, ')'); if (tmp == NULLSTR) { varstrFree(s1); return(time); } *tmp = '\0'; hh = strToInt(hhstr); mm = strToInt(mmstr); ss = strToInt(ssstr); if (hh == -1 || mm == -1 || ss == -1) { varstrFree(s1); return(time); } time.h = hh; time.m = mm; time.s = ss; varstrFree(s1); return(time); } /* Gets the DateTime portion of the string with the form "(h:m:s,m|d|y)", "(m|d|y), or "(h:m:s)". If conversion failed, {-1, -1, -1, 0, 0, 0} will be returned. */ DateTime strToDateTime(str) char *str; { Time t; Date d; DateTime dt; t = strToTime(str); d = strToDate(str); dt.t = t; dt.d = d; return(dt); } /* strToSize: given a SIZE string of the form, "[]" where is [k|K|m|M|g|G|t|T|p|P] [b|w]. RETURN: the corresponding Size struct. NOTE: If an error has occurred during conversion such as BADVAL or BADSUFFIX, the Size structure returned will be {-1, 0, BYTES}. */ Size strToSize(str) char *str; { int havebw = 0; char *pc; Size sizeval; Size defsizeval = { -1, 0, BYTES}; if (str == NULLSTR) { return(defsizeval); } sizeval.units = BYTES; sizeval.shift = 0; sizeval.num = strtol(str, &pc, 10); if (pc == str) /* no numeric part */ return (defsizeval); switch (*pc) { case '\0': break; case 'k': case 'K': sizeval.shift = 10; break; case 'm': case 'M': sizeval.shift = 20; break; case 'g': case 'G': sizeval.shift = 30; break; case 't': case 'T': sizeval.shift = 40; break; case 'p': case 'P': sizeval.shift = 50; break; case 'b': case 'B': havebw = 1; break; case 'w': case 'W': havebw = 1; sizeval.units = WORDS; break; default: return (defsizeval); /* invalid string */ } if (*pc != '\0') pc++; if (*pc != '\0') { if (havebw) return (defsizeval); /* invalid string */ switch (*pc) { case 'b': case 'B': break; case 'w': case 'W': sizeval.units = WORDS; break; default: return (defsizeval); } } return (sizeval); } /* sizeToStr: given a SIZE structure, convert appropriately into a string. */ void sizeToStr(sizeval, cvnbuf) Size sizeval; char *cvnbuf; { (void)sprintf(cvnbuf, "%ld", sizeval.num); switch (sizeval.shift) { case 0: break; case 10: strcat(cvnbuf, "k"); break; case 20: strcat(cvnbuf, "m"); break; case 30: strcat(cvnbuf, "g"); break; case 40: strcat(cvnbuf, "t"); break; case 50: strcat(cvnbuf, "p"); } if (sizeval.units & WORDS) strcat(cvnbuf, "w"); else strcat(cvnbuf, "b"); } /* strtimeToSecs: given a time string (hh:mm:ss[.ms]), return the equivalent # of secs. NOTE: ms precision can potentially be lost. If conversion failed, then this will return a -1. */ int strtimeToSecs(char *times) { int hh, mm, ss, ms; char *hhstr, *mmstr, *ssstr, *msstr; char *timestr = NULLSTR; int secs; dynamic_strcpy(×tr, times); hhstr = strtok(timestr, ":"); if (hhstr == NULLSTR) { hh = 0; } else { hh = strToInt(hhstr); if (hh == -1) { varstrFree(timestr); return(-1); } } mmstr = strtok(NULL, ":"); if (mmstr == NULLSTR) { mm = 0; } else { mm = strToInt(mmstr); if (mm == -1) { varstrFree(timestr); return(-1); } } ssstr = strtok(NULL, "."); if (ssstr == NULLSTR) { ss = 0; } else { ss = strToInt(ssstr); if (ss == -1) { varstrFree(timestr); return(-1); } } msstr = strtok(NULL, "."); if (msstr == NULLSTR) { ms = 0; } else { ms = strToInt(msstr); if (ms == -1) { varstrFree(timestr); return(-1); } } /* 1 s = 10^3 ms */ secs = hh * 3600 + mm * 60 + ss + (ms / 1000); varstrFree(timestr); return(secs); } /* datecmp: compares 2 dates and returns an: int < 0 if d1 is less than d2, int = 0 if d1 is equal to d2, int > 0 if d1 is greater than d2. */ int datecmp(d1, d2) Date d1; Date d2; { struct tm tdate1; struct tm tdate2; time_t td1; time_t td2; tdate1.tm_mon = d1.m - 1; tdate1.tm_mday = d1.d; tdate1.tm_year = d1.y - 1900; tdate1.tm_hour = 0; tdate1.tm_min = 59; tdate1.tm_sec = 60; tdate1.tm_isdst = -1; tdate2.tm_mon = d2.m - 1; tdate2.tm_mday = d2.d; tdate2.tm_year = d2.y - 1900; tdate2.tm_hour = 0; tdate2.tm_min = 59; tdate2.tm_sec = 60; tdate2.tm_isdst = -1; td1 = mktime(&tdate1); td2 = mktime(&tdate2); return((int)(td1 - td2)); } /* timecmp: compares 2 times and returns an: int < 0 if t1 is less than t2, int = 0 if t1 is equal to t2, int > 0 if t1 is greater than t2. */ int timecmp(t1, t2) Time t1; Time t2; { char timestr[10]; int secs1 = 0; int secs2 = 0; (void)sprintf(timestr, "%d:%d:%d", t1.h, t1.m, t1.s); secs1 = strtimeToSecs(timestr); (void)sprintf(timestr, "%d:%d:%d", t2.h, t2.m, t2.s); secs2 = strtimeToSecs(timestr); if (secs1 > secs2) return(1); if (secs1 < secs2) return(-1); return(0); } /* get the current date/time. */ DateTime datetimeGet(void) { time_t now; struct tm *t; DateTime nowdt; now = time((time_t *)NULL); t = localtime(&now); nowdt.t.h = t->tm_hour; nowdt.t.m = t->tm_min; nowdt.t.s = t->tm_sec; nowdt.d.m = t->tm_mon + 1; nowdt.d.d = t->tm_mday; nowdt.d.y = t->tm_year + 1900; return(nowdt); } /* get the current date/time. */ DateTime datetimeGetAndAdd(secs) time_t secs; { time_t now; struct tm *t; DateTime nowdt; now = time((time_t *)NULL); now += secs; t = localtime(&now); nowdt.t.h = t->tm_hour; nowdt.t.m = t->tm_min; nowdt.t.s = t->tm_sec; nowdt.d.m = t->tm_mon + 1; nowdt.d.d = t->tm_mday; nowdt.d.y = t->tm_year + 1900; return(nowdt); } /* datetimeToSecs: converts a DateTime structure into the # of seconds epoch (00:00:00 January 1, 1970) */ int datetimeToSecs(dt) DateTime dt; { DateTime now; struct tm tdate; now = datetimeGet(); if (datecmp(dt.d, strToDate("(0|0|0)")) != 0) { tdate.tm_mon = dt.d.m - 1; tdate.tm_mday = dt.d.d; tdate.tm_year = dt.d.y - 1900; } else { tdate.tm_mon = now.d.m - 1; tdate.tm_mday = now.d.d; tdate.tm_year = now.d.y - 1900; } if (timecmp(dt.t, strToTime("(-1:-1:-1)")) != 0) { tdate.tm_hour = dt.t.h; tdate.tm_min = dt.t.m; tdate.tm_sec = dt.t.s; } else { tdate.tm_hour = now.t.h; /* no time portion */ tdate.tm_min = now.t.m; tdate.tm_sec = now.t.s; } tdate.tm_isdst = -1; return(mktime(&tdate)); } /* datetimecmp: compares 2 dateTimes and returns an: int < 0 if dt1 is less than dt2, int = 0 if dt1 is equal to dt2, int > 0 if dt1 is greater than dt2. */ int datetimecmp(dt1, dt2) DateTime dt1; DateTime dt2; { int dt1s; int dt2s; dt1s = datetimeToSecs(dt1); dt2s = datetimeToSecs(dt2); return(dt1s - dt2s); } /* * normalizeSize - normalize two size values, adjust so the shift * counts are the same. */ int normalizeSize(a, b, ta, tb) Size *a; Size *b; Size *ta; Size *tb; { int adj; unsigned long temp; /* * we do the work in copies of the original attributes * to preserve the original (in case of error) */ *ta = *a; *tb = *b; /* if either unit is in bytes, then both must be */ if ((ta->units == WORDS) && (tb->units != WORDS)) { ta->num *= sizeof(int); ta->units = BYTES; } else if ((ta->units != WORDS) && (tb->units == WORDS)) { tb->num *= sizeof(int); tb->units = BYTES; } adj = ta->shift - tb->shift; if (adj > 0) { temp = ta->num; if ((adj > sizeof(int) * 8) || (((temp << adj) >> adj) != ta->num)) return (-1); /* would overflow */ ta->shift = tb->shift; ta->num = ta->num << adj; } else if (adj < 0) { adj = -adj; temp = tb->num; if ((adj > sizeof(int) * 8) || (((temp << adj) >> adj) != tb->num)) return (-1); /* would overflow */ tb->shift = ta->shift; tb->num = tb->num << adj; } return(0); } /* * comp_size - compare two size structures. * * Returns: +1 if 1st > 2nd * 0 if 1st == 2nd * -1 if 1st < 2nd */ int sizecmp(a, w) Size a; Size w; { Size tmpa; Size tmpw; if (normalizeSize(&a, &w, &tmpa, &tmpw) != 0) /* different suffix */ { if (tmpa.shift > tmpw.shift) return (1); else if (tmpa.shift < tmpw.shift) return (-1); else return (0); } else if (tmpa.num > tmpw.num) /* now have same suffixes */ return (1); else if (tmpa.num < tmpw.num) return (-1); else return (0); } static long int hashptr(void *ptr) { return((long int)ptr % MAXDARRAY); } /* getHashValue: returns the actual hash value that contains 'ptr'. A value of -1 means ptr could not be found. */ static int getHashValue(void *ptr) { int hashvalue1, hashvalue; hashvalue1 = hashptr(ptr); hashvalue = hashvalue1; while (d_array[hashvalue].ptr != ptr) /* collision resolution */ { hashvalue = (hashvalue + 1) % MAXDARRAY; assert(hashvalue != hashvalue1); /* should find something */ } return(hashvalue); } /* getHashValueToStore: returns the hash value where 'ptr' could be stored. A value of -1 means the hash table is full. */ static int getHashValueToStore(void *ptr) { int hashvalue1, hashvalue; hashvalue1 = hashptr(ptr); hashvalue = hashvalue1; while (d_array[hashvalue].ptr != NULL) /* collision resolution */ { hashvalue = (hashvalue + 1) % MAXDARRAY; assert(hashvalue != hashvalue1); } return(hashvalue); } /* dynamicArraySize: returns the num elements in the dynamic 'array', or 0 if 'array' is NULL, or -1 if 'array' could not be identified. */ int dynamicArraySize(void *array) { int hashvalue; if (array == NULL) return(0); hashvalue = getHashValue(array); return(d_array[hashvalue].numElems); } /* initDynamicArray: initializes a dynamic array of size numElems*elementSize RETURNS: pointer to malloc-ed storage which could be NULL if malloc-ing failed. NOTE: Can't have a 0 for numElems */ void *initDynamicArray(numElems, elementSize) size_t numElems; size_t elementSize; { void *newspace; int hashvalue; if ((int) numElems <= 0) return(NULL); newspace = calloc(numElems, elementSize); if (newspace != NULL) { hashvalue = getHashValueToStore(newspace); d_array[hashvalue].ptr = newspace; d_array[hashvalue].numElems = numElems; } assert(newspace != NULL); fflush(stdout); return(newspace); } /* extendDynamicArray: expands the dynamic 'array' so that minNumElements can at least fit. If array is NULL, then it is automatically initialized. Calling extendDynamicArray(NULL, minNumElems, elementSize) is the same as initDynamicArray(minNumElemns, elementSize) NOTE: minNumElems must not be zero !*/ void *extendDynamicArray(array, minNumElems, elementSize) void *array; /* a dynamic array */ size_t minNumElems; /* minimum # of elements in the array */ size_t elementSize; /* size of an element of an array */ { void *newspace; int curNumElems; int hashvalue; assert((int) minNumElems > 0); if (array == NULL) { return(initDynamicArray(minNumElems, elementSize)); } curNumElems = dynamicArraySize(array); if (minNumElems > curNumElems) /* not enough space in the array */ { if (array == NULL) newspace = malloc(minNumElems * elementSize); else newspace = realloc(array, minNumElems * elementSize); if (newspace != NULL) { hashvalue = getHashValue(array); if (array != newspace) /* reuse same slot */ { d_array[hashvalue].ptr = NULL; hashvalue = getHashValueToStore(newspace); d_array[hashvalue].ptr = newspace; } d_array[hashvalue].numElems = minNumElems; return(newspace); } } return(array); } void freeDynamicArray( void *array /* array to free up storage */ ) { int hashvalue; if (array == NULL) return; hashvalue = getHashValue(array); d_array[hashvalue].ptr = NULL; free(array); } void printDynamicArrayTable(void) { int i; printf("Printing Dynamic Array Table===============================\n"); for (i = 0; i < MAXDARRAY; i++) (void)printf("(%x, %d)\n", d_array[i].ptr, d_array[i].numElems); } void datePrint(d) Date d; { printf("%02d/%02d/%02d", d.m, d.d, d.y); } void timePrint(t) Time t; { printf("%02d:%02d:%02d", t.h, t.m, t.s); } void datetimePrint(dt) DateTime dt; { if (datecmp(dt.d, strToDate("(0|0|0)")) != 0) { printf("("); datePrint(dt.d); if (timecmp(dt.t, strToTime("(-1:-1:-1)")) != 0) { printf("@"); timePrint(dt.t); } printf(")"); } else if (timecmp(dt.t, strToTime("(-1:-1:-1)")) != 0) { printf("("); timePrint(dt.t); printf(")"); } } void sizePrint(s, readable) Size s; int readable; /* if 1, then print size val in human readable form */ { char sizestr[45]; /* should be able to support up to 128-bits sizes */ if (readable) { sizeToStr(s, (char *)sizestr); printf("%s", sizestr ? sizestr : "null"); } else { printf("NUM: %ld SHIFT: %d UNIT: %d", s.num, s.shift, s.units); } } void intRangePrint(r) IntRange r; { printf("(%d, %d)", r.lo, r.hi); } void floatRangePrint(r) FloatRange r; { printf("(%7.2f, %7.2f)", r.lo, r.hi); } void dayofweekPrint(dow) Dayofweek dow; { if (dow < NUMDAYOFWEEK) printf("%s", dayofweekVal[dow]); else printf("%d", dow); } void actPrint(act) Action act; { if (act < NUMACTS) printf("%s", actVal[act]); else printf("%d", act); } void cprPrint(cpr) Comp cpr; { if (cpr < NUMCPRS) printf("%s", cprVal[cpr]); else printf("%d", cpr); } void dayofweekRangePrint(r) DayofweekRange r; { char *loday = NULLSTR; char *hiday = NULLSTR; if (r.lo < NUMDAYOFWEEK) loday = dayofweekVal[r.lo]; if (r.hi < NUMDAYOFWEEK) hiday = dayofweekVal[r.hi]; if (loday != NULLSTR && hiday != NULLSTR) printf("(%s, %s)", loday, hiday); else if (loday == NULLSTR && hiday != NULLSTR) printf("(%d, %s)", r.lo, hiday); else if (loday != NULLSTR && hiday == NULLSTR) printf("(%s, %d)", loday, r.hi); else printf("(%d, %d)", r.lo, r.hi); } void dateRangePrint(d) DateRange d; { printf("("); datePrint(d.lo); printf(", "); datePrint(d.hi); printf(")"); } void timeRangePrint(t) TimeRange t; { printf("("); timePrint(t.lo); printf(", "); timePrint(t.hi); printf(")"); } void datetimeRangePrint(dt) DateTimeRange dt; { printf("("); datetimePrint(dt.lo); printf(", "); datetimePrint(dt.hi); printf(")"); } void sizeRangePrint(s, readable) SizeRange s; int readable; { printf("("); sizePrint(s.lo, readable); printf(", "); sizePrint(s.hi, readable); printf(")"); } /* Given a string of the form "(int, int)", return a corresponding Range structure. If conversion fails, return {0, 0}. */ IntRange strToIntRange(str) char *str; { char *s1 = NULLSTR; char *lo, *hi, *tmp; IntRange range = {0, 0}; if (str == NULLSTR) { return(range); } dynamic_strcpy(&s1, str); lo = strchr(s1, '('); if (lo == NULLSTR) { varstrFree(s1); return(range); } lo++; hi = strchr(lo, ','); if (hi == NULLSTR) { varstrFree(s1); return(range); } *hi = '\0'; hi++; tmp = strchr(hi, ')'); if (tmp == NULLSTR) { varstrFree(s1); return(range); } *tmp = '\0'; range.lo = strToInt(lo); range.hi = strToInt(hi); varstrFree(s1); return(range); } /* Given a string of the form "(float, float)", return a corresponding Range structure. If conversion fails, return {0.0, 0.0}. */ FloatRange strToFloatRange(str) char *str; { char *s1 = NULLSTR; char *lo, *hi, *tmp; FloatRange range = {0.0, 0.0}; if (str == NULLSTR) { return(range); } dynamic_strcpy(&s1, str); lo = strchr(s1, '('); if (lo == NULLSTR) { varstrFree(s1); return(range); } lo++; hi = strchr(lo, ','); if (hi == NULLSTR) { varstrFree(s1); return(range); } *hi = '\0'; hi++; tmp = strchr(hi, ')'); if (tmp == NULLSTR) { varstrFree(s1); return(range); } *tmp = '\0'; range.lo = strToFloat(lo); range.hi = strToFloat(hi); varstrFree(s1); return(range); } /* Given a string of the form "(dow, dow)", return a corresponding Range structure. If conversion fails, return {SUN, SUN}. */ DayofweekRange strToDayofweekRange(str) char *str; { char *s1 = NULLSTR; char *lo, *hi, *tmp; DayofweekRange range = {SUN, SUN}; if (str == NULLSTR) { return(range); } dynamic_strcpy(&s1, str); lo = strchr(s1, '('); if (lo == NULLSTR) { varstrFree(s1); return(range); } lo++; /* skip leading empty spaces */ while (*lo == ' ') lo++; hi = strchr(lo, ','); if (hi == NULLSTR) { varstrFree(s1); return(range); } *hi = '\0'; hi++; /* skip leading empty spaces */ while (*hi == ' ') hi++; tmp = strchr(hi, ')'); if (tmp == NULLSTR) { varstrFree(s1); return(range); } *tmp = '\0'; range.lo = strToDayofweek(lo); range.hi = strToDayofweek(hi); varstrFree(s1); return(range); } /* Given a string of the form "(date, date)", return a corresponding Range structure. If conversion fails, return {{1, 1, 1970}, {1, 1, 1970}}. */ DateRange strToDateRange(str) char *str; { char *s1 = NULLSTR; char *lo, *hi, *tmp; DateRange range = {{1, 1, 1970}, {1, 1, 1970}}; if (str == NULLSTR) { return(range); } dynamic_strcpy(&s1, str); lo = strchr(s1, '('); if (lo == NULLSTR) { varstrFree(s1); return(range); } lo++; hi = strchr(lo, ','); if (hi == NULLSTR) { varstrFree(s1); return(range); } *hi = '\0'; hi++; /* locates last occurrence */ tmp = strrchr(hi, ')'); if (tmp == NULLSTR) { varstrFree(s1); return(range); } *tmp = '\0'; range.lo = strToDate(lo); range.hi = strToDate(hi); varstrFree(s1); return(range); } /* Given a string of the form "(time, time)", return a corresponding Range structure. If conversion fails, return {{0, 0, 0}, {0, 0, 0}}. */ TimeRange strToTimeRange(str) char *str; { char *s1 = NULLSTR; char *lo, *hi, *tmp; TimeRange range = {{0, 0, 0}, {0, 0, 0}}; if (str == NULLSTR) { return(range); } dynamic_strcpy(&s1, str); lo = strchr(s1, '('); if (lo == NULLSTR) { varstrFree(s1); return(range); } lo++; hi = strchr(lo, ','); if (hi == NULLSTR) { varstrFree(s1); return(range); } *hi = '\0'; hi++; /* locates last occurrence */ tmp = strrchr(hi, ')'); if (tmp == NULLSTR) { varstrFree(s1); return(range); } *tmp = '\0'; range.lo = strToTime(lo); range.hi = strToTime(hi); varstrFree(s1); return(range); } /* Given a string of the form "(datetime, datetime)", return a corresponding DateTimeRange structure. If conversion fails, return {{-1, -1, -1, 0, 0, 0}, {-1, -1, -1, 0, 0, 0}}. */ DateTimeRange strToDateTimeRange(str) char *str; { char *s1 = NULLSTR; char *lo, *hi, *tmp; DateTimeRange range = {{ -1, -1, -1, 0, 0, 0}, { -1, -1, -1, 0, 0, 0}}; if (str == NULLSTR) { return(range); } dynamic_strcpy(&s1, str); lo = strchr(s1, '('); if (lo == NULLSTR) { varstrFree(s1); return(range); } lo++; hi = strchr(lo, ','); if (hi == NULLSTR) { varstrFree(s1); return(range); } *hi = '\0'; hi++; /* locates last occurrence */ tmp = strrchr(hi, ')'); if (tmp == NULLSTR) { varstrFree(s1); return(range); } *tmp = '\0'; range.lo = strToDateTime(lo); range.hi = strToDateTime(hi); varstrFree(s1); return(range); } /* Given a string of the form "(size, size)", return a corresponding Range structure. If conversion fails, return { {-1, 0, BYTES},{-1, 0, BYTES} }. */ SizeRange strToSizeRange(str) char *str; { char *s1 = NULLSTR; char *lo, *hi, *tmp; SizeRange range = {{ -1, 0, BYTES}, { -1, 0, BYTES}}; if (str == NULLSTR) { return(range); } dynamic_strcpy(&s1, str); lo = strchr(s1, '('); if (lo == NULLSTR) { varstrFree(s1); return(range); } lo++; hi = strchr(lo, ','); if (hi == NULLSTR) { varstrFree(s1); return(range); } *hi = '\0'; hi++; tmp = strchr(hi, ')'); if (tmp == NULLSTR) { varstrFree(s1); return(range); } *tmp = '\0'; range.lo = strToSize(lo); range.hi = strToSize(hi); varstrFree(s1); return(range); } /* * sizeRangecmp: - compares 2 size ranges and returns 0 if they're the same; 1 otherwise. */ int sizeRangecmp(r1, r2) SizeRange r1; SizeRange r2; { if ((sizecmp(r1.lo, r2.lo) == 0) && \ (sizecmp(r1.hi, r2.hi) == 0)) return(0); return(1); } /* * sizeStrcmp: - converts the 2 string arguments into sizes, and then compares t hem using sizecmp. * * Returns: +1 if 1st > 2nd * 0 if 1st == 2nd * -1 if 1st < 2nd */ int sizeStrcmp(char *a, char *w) { Size tmpa; Size tmpw; tmpa = strToSize(a); tmpw = strToSize(w); return(sizecmp(tmpa, tmpw)); } /* sizeRangeStrcmp: compares 2 SizeRange strings and returns 0 if they are equal; non-zero otherwise. */ int sizeRangeStrcmp(char *str1, char *str2) { SizeRange sr1, sr2; sr1 = strToSizeRange(str1); sr2 = strToSizeRange(str2); return(sizeRangecmp(sr1, sr2)); } IntRange toIntRange(i1, i2) int i1; int i2; { IntRange i; i.lo = i1; i.hi = i2; return(i); } FloatRange toFloatRange(f1, f2) double f1; double f2; { FloatRange f; f.lo = f1; f.hi = f2; return(f); } DayofweekRange toDayofweekRange(dow1, dow2) Dayofweek dow1; Dayofweek dow2; { DayofweekRange dow; dow.lo = dow1; dow.hi = dow2; return(dow); } DateRange toDateRange(d1, d2) Date d1; Date d2; { DateRange dr; dr.lo = d1; dr.hi = d2; return(dr); } TimeRange toTimeRange(t1, t2) Time t1; Time t2; { TimeRange tr; tr.lo = t1; tr.hi = t2; return(tr); } DateTimeRange toDateTimeRange(dt1, dt2) DateTime dt1; DateTime dt2; { DateTimeRange dr; dr.lo = dt1; dr.hi = dt2; return(dr); } SizeRange toSizeRange(sz1, sz2) Size sz1; Size sz2; { SizeRange rsz; rsz.lo = sz1; rsz.hi = sz2; return(rsz); } /* adds 2 Sizes values together. For values of different suffixes, normalization will take place; the unit in the final result is the unit of the smaller of the two. */ /* NOTE: If adding the two values would result in an overflow during the normalization step, then -1b is returned. To avoid overflow, it is best that the operands are of the same suffix*/ Size sizeAdd(a, w) Size a; Size w; { Size tmpa; Size tmpw; Size ret = { -1, 0, BYTES}; if (normalizeSize(&a, &w, &tmpa, &tmpw) != 0) /* oveflow */ { return(ret); } /* now have same suffixes, normalized! */ ret.shift = tmpa.shift; ret.units = tmpa.units; ret.num = tmpa.num + tmpw.num; return(ret); } /* subtracts 2 Sizes values together. For values of different suffixes, normalization will take place; the suffix in the final result is the suffix of the smaller of the two. */ /* NOTE: If subtracting the two values would result in an overflow during the normalization step, then -1b is returned. To avoid overflow, it is best that the operands are of the same suffix*/ Size sizeSub(a, w) Size a; Size w; { Size tmpa; Size tmpw; Size ret = { -1, 0, BYTES}; if (normalizeSize(&a, &w, &tmpa, &tmpw) != 0) /* oveflow */ { return(ret); } /* now have same suffixes, normalized! */ ret.shift = tmpa.shift; ret.units = tmpa.units; ret.num = tmpa.num - tmpw.num; return(ret); } /* multiplies 2 Sizes values together. For values of different suffixes, normalization will take place; the suffix in the final result is the suffix of the smaller of the two. */ /* NOTE: If multiplying the two values would result in an overflow during the normalization step, then -1b is returned. To avoid overflow, it is best that the operands are of the same suffix*/ Size sizeMul(a, w) Size a; Size w; { Size tmpa; Size tmpw; Size ret = { -1, 0, BYTES}; if (normalizeSize(&a, &w, &tmpa, &tmpw) != 0) /* oveflow */ { return(ret); } /* now have same suffixes, normalized! */ ret.shift = tmpa.shift; ret.units = tmpa.units; ret.num = tmpa.num * tmpw.num; return(ret); } /* divides 2 Sizes values together. For values of different suffixes, normalization will take place; the suffix in the final result is the suffix of the smaller of the two. */ /* NOTE: If dividing the two values would result in an overflow during the normalization step, then -1b is returned. To avoid overflow, it is best that the operands are of the same suffix*/ Size sizeDiv(a, w) Size a; Size w; { Size tmpa; Size tmpw; Size ret = { -1, 0, BYTES}; if (normalizeSize(&a, &w, &tmpa, &tmpw) != 0) /* oveflow */ { return(ret); } /* now have same suffixes, normalized! */ ret.shift = tmpa.shift; ret.units = tmpa.units; ret.num = tmpa.num / tmpw.num; return(ret); } /* -sz */ Size sizeUminus(sz) Size sz; { Size ret; ret.shift = sz.shift; ret.units = sz.units; ret.num = -sz.num; return(ret); } /* concatentate 2 malloc-ed strings into one string that is returned. */ /* NOTE: The returned string is a pointer to a malloced area that be */ /* reused by this routine over and over again. So be sure that */ /* when assigning values from this routine, be sure to duplicate */ /* the value in other malloc-ed area. */ char * strCat(char *str1, char *str2) { char *catstr = NULLSTR; /* a string whose value is str1. */ dynamic_strcpy(&catstr, str1); /* Append to cat string the value of str2. */ dynamic_strcat(&catstr, str2); varstrModScope(catstr, -1); /* temporary variable strings */ /* have scope -1 */ return(catstr); } /* Malloc table */ void mallocSubIndexTableAdd(struct mallocIndex_type *ptr) { struct mallocSubIndex_type *elem; int index; index = mallocSubIndexTableHash(ptr->mptr->scope); elem = (struct mallocSubIndex_type *) \ malloc((size_t)sizeof(struct mallocSubIndex_type)); elem->ptr = ptr; elem->link = mallocSubIndexTable[index]; mallocSubIndexTable[index] = elem; } void mallocSubIndexTableFree(struct mallocIndex_type *ptr) { int index; struct mallocSubIndex_type *v, *v_before; index = mallocSubIndexTableHash(ptr->mptr->scope); v_before = NULL; for (v = mallocSubIndexTable[index]; v; v = v->link) { if (v->ptr == ptr) { if (v_before == NULL) { mallocSubIndexTable[index] = v->link; } else { v_before->link = v->link; } free(v); return; } v_before = v; } } void mallocIndexTableAdd(struct malloc_type *mptr) { struct mallocIndex_type *elem; int index; index = mallocIndexTableHash(mptr->pptr); elem = (struct mallocIndex_type *) \ malloc((size_t)sizeof(struct mallocIndex_type)); elem->mptr = mptr; elem->link = mallocIndexTable[index]; mallocIndexTable[index] = elem; mallocSubIndexTableAdd(elem); } void mallocIndexTableFree(struct malloc_type *mptr) { int index; struct mallocIndex_type *v, *v_before; index = mallocIndexTableHash(mptr->pptr); v_before = NULL; for (v = mallocIndexTable[index]; v; v = v->link) { if (v->mptr == mptr) { if (v_before == NULL) { mallocIndexTable[index] = v->link; } else { v_before->link = v->link; } mallocSubIndexTableFree(v); free(v); return; } v_before = v; } } void mallocIndexTableFreeNoIndex(struct malloc_type *mptr) { int index; struct mallocIndex_type *v; index = mallocIndexTableHash(mptr->pptr); for (v = mallocIndexTable[index]; v; v = v->link) { if (v->mptr == mptr) { mallocSubIndexTableFree(v); return; } } } void mallocIndexTableFreeNoSubIndex(struct malloc_type *mptr) { int index; struct mallocIndex_type *v, *v_before; index = mallocIndexTableHash(mptr->pptr); v_before = NULL; for (v = mallocIndexTable[index]; v; v = v->link) { if (v->mptr == mptr) { if (v_before == NULL) { mallocIndexTable[index] = v->link; } else { v_before->link = v->link; } free(v); return; } v_before = v; } } void mallocTableAdd(void *ptr, void *pptr, int scope) { struct malloc_type *v_elem; int index; index = mallocTableHash(ptr); v_elem = (struct malloc_type *) \ malloc((size_t)sizeof(struct malloc_type)); v_elem->ptr = ptr; v_elem->pptr = pptr; v_elem->scope = scope; v_elem->link = mallocTable[index]; mallocTable[index] = v_elem; mallocIndexTableAdd(v_elem); } void mallocTablePrint(void) { int i; struct malloc_type *v; struct mallocIndex_type *v2; struct mallocSubIndex_type *v3; for (i = 0; i < MALLOCLEN; i++) { printf("mallocTable[%d]: ======================================\n", i); for (v = mallocTable[i]; v; v = v->link) { printf("%d:%x: (%x, %x, %d, %x)\n", i, v, v->ptr, v->pptr, v->scope, v->link); } } for (i = 0; i < MALLOC_INDEX_LEN; i++) { printf("mallocIndexTable[%d]: ======================================\n", i); for (v2 = mallocIndexTable[i]; v2; v2 = v2->link) { printf("%d:%x: (mptr: %x, hashkey-pptr: %x)\n", i, v2, v2->mptr, v2->mptr->pptr); } } for (i = 0; i < MALLOC_SUBINDEX_LEN; i++) { printf("mallocSubIndexTable[%d]: ======================================\n", i); for (v3 = mallocSubIndexTable[i]; v3; v3 = v3->link) { printf("%d:%x: (%x, hashkey-scope: %d)\n", i, v3, v3->ptr, v3->ptr->mptr->scope); } } } void mallocTableInit(void) { int i; for (i = 0; i < MALLOCLEN; i++) { mallocTable[i] = (struct malloc_type *)NULL; } for (i = 0; i < MALLOC_INDEX_LEN; i++) { mallocIndexTable[i] = (struct mallocIndex_type *)NULL; } for (i = 0; i < MALLOC_SUBINDEX_LEN; i++) { mallocSubIndexTable[i] = (struct mallocSubIndex_type *)NULL; } } /* Returns 1 if 'ptr' is a entry in the malloc table ; 0 otherwise. */ int inMallocTable(void *ptr) { int index; struct malloc_type *v; index = mallocTableHash(ptr); for (v = mallocTable[index]; v; v = v->link) { if (v->ptr == ptr) { return(1); } } return(0); } /* NOTE: This will automatically reject NULL values or malloc-ed storage */ /* it doesn't know about */ void mallocTableFree(void *ptr) { int index; struct malloc_type *v, *v_before; index = mallocTableHash(ptr); v_before = NULL; for (v = mallocTable[index]; v; v = v->link) { if (v->ptr == ptr) { free(ptr); if (v_before == NULL) { mallocTable[index] = v->link; } else { v_before->link = v->link; } mallocIndexTableFree(v); free(v); return; } v_before = v; } } /* mallocTableFreeNoIndex: this is the same as mallocTableFree except */ /* freeing the corresponding entry in the */ /* mallocTableIndex will not be done. */ void mallocTableFreeNoIndex(void *ptr) { int index; struct malloc_type *v, *v_before; index = mallocTableHash(ptr); v_before = NULL; for (v = mallocTable[index]; v; v = v->link) { if (v->ptr == ptr) { free(ptr); if (v_before == NULL) { mallocTable[index] = v->link; } else { v_before->link = v->link; } mallocIndexTableFreeNoIndex(v); free(v); return; } v_before = v; } } void mallocTableFreeNoSubIndex(void *ptr) { int index; struct malloc_type *v, *v_before; index = mallocTableHash(ptr); v_before = NULL; for (v = mallocTable[index]; v; v = v->link) { if (v->ptr == ptr) { free(ptr); if (v_before == NULL) { mallocTable[index] = v->link; } else { v_before->link = v->link; } mallocIndexTableFreeNoSubIndex(v); free(v); return; } v_before = v; } } /* This is like mallocTableFreeNoSubIndex except the last ptr is not freed */ void mallocTableFreeNoSubIndex2(void *ptr) { int index; struct malloc_type *v, *v_before; index = mallocTableHash(ptr); v_before = NULL; for (v = mallocTable[index]; v; v = v->link) { if (v->ptr == ptr) { if (v_before == NULL) { mallocTable[index] = v->link; } else { v_before->link = v->link; } mallocIndexTableFreeNoSubIndex(v); free(v); return; } v_before = v; } } void mallocTableFreeByPptr(void *pptr) { int index; struct mallocIndex_type *v, *v_before, *linkptr; index = mallocIndexTableHash(pptr); v_before = NULL; v = mallocIndexTable[index]; while (v) { linkptr = v->link; if (v->mptr->pptr == pptr) { mallocTableFreeNoIndex(v->mptr->ptr); if (v_before == NULL) { mallocIndexTable[index] = linkptr; } else { v_before->link = linkptr; } free(v); } else { v_before = v; } v = linkptr; } } void mallocTableFreeByScope(int scope, void (*freefunc)(void)) { int index; struct mallocSubIndex_type *v, *v_before, *linkptr; void **objptrs = NULL; int beforecnt, aftercnt, numptrs, i; index = mallocSubIndexTableHash(scope); v_before = NULL; v = mallocSubIndexTable[index]; while (v) { linkptr = v->link; if (v->ptr->mptr->scope == scope) { beforecnt = dynamicArraySize(objptrs); objptrs = (void *)extendDynamicArray(objptrs, beforecnt + 1, sizeof(void *)); aftercnt = dynamicArraySize(objptrs); if (aftercnt > beforecnt) { objptrs[beforecnt] = v->ptr->mptr->ptr; } mallocTableFreeNoSubIndex2(v->ptr->mptr->ptr); if (v_before == NULL) { mallocSubIndexTable[index] = linkptr; } else { v_before->link = linkptr; } free(v); } else { v_before = v; } v = linkptr; } numptrs = dynamicArraySize(objptrs); for (i = 0; i < numptrs; i++) { freefunc(objptrs[i]); } freeDynamicArray(objptrs); } void mallocTableModScope(void *ptr, int newscope) { int index, index2; struct malloc_type *v; struct mallocIndex_type *v2; struct mallocIndex_type *index_entry; index = mallocTableHash(ptr); index_entry = NULL; for (v = mallocTable[index]; v; v = v->link) { if (v->ptr == ptr) { /* hash lookup against index2 */ index2 = mallocIndexTableHash(v->pptr); for (v2 = mallocIndexTable[index2]; v2; v2 = v2->link) { if (v2->mptr == v) { /* hash lookup against scope */ mallocSubIndexTableFree(v2); index_entry = v2; break; } } v->scope = newscope; if (index_entry != NULL) { mallocSubIndexTableAdd(index_entry); } return; } } } /* safe modification of scope means only non-global variables (scope != 0) will be allowed to be modified */ void mallocTableSafeModScope(void *ptr, int newscope) { int index, index2; struct malloc_type *v; struct mallocIndex_type *v2; struct mallocIndex_type *index_entry; index = mallocTableHash(ptr); index_entry = NULL; for (v = mallocTable[index]; v; v = v->link) { if (v->ptr == ptr && v->scope != 0) { /* hash lookup against index2 */ index2 = mallocIndexTableHash(v->pptr); for (v2 = mallocIndexTable[index2]; v2; v2 = v2->link) { if (v2->mptr == v) { /* hash lookup against scope */ mallocSubIndexTableFree(v2); index_entry = v2; break; } } v->scope = newscope; if (index_entry != NULL) { mallocSubIndexTableAdd(index_entry); } return; } } } /* * intInRange - returns 1 if i is in range, 0 otherwise. * */ int inIntRange(i, range) int i; IntRange range; { return(i >= range.lo && i <= range.hi); } int inFloatRange(f, range) double f; FloatRange range; { return(f >= range.lo && f <= range.hi); } /* * dayofweekInRange - returns 1 if dow is in range, 0 otherwise. * */ int inDayofweekRange(dow, range) Dayofweek dow; DayofweekRange range; { return(dow >= range.lo && dow <= range.hi); } /* * dateInRange - returns 1 if d is in range, 0 otherwise. * */ int inDateRange(d, range) Date d; DateRange range; { return(datecmp(d, range.lo) >= 0 && datecmp(d, range.hi) <= 0); } /* * timeInRange - returns 1 if t is in range, 0 otherwise. * */ int inTimeRange(t, range) Time t; TimeRange range; { return(timecmp(t, range.lo) >= 0 && timecmp(t, range.hi) <= 0); } int inDateTimeRange(dt, range) DateTime dt; DateTimeRange range; { DateTime now; struct tm now_tm; time_t now_t; struct tm *t; /* if datetimes contain only time portions (i.e. hh:mm:ss) and low > hi, then adjust the hi by 1 day */ if (datecmp(range.lo.d, strToDate("(0|0|0)")) == 0 && \ datecmp(range.hi.d, strToDate("(0|0|0)")) == 0 && \ datetimecmp(range.lo, range.hi) > 0) { now = datetimeGet(); range.lo.d.m = now.d.m; range.lo.d.d = now.d.d; range.lo.d.y = now.d.y; now_tm.tm_mon = now.d.m - 1; now_tm.tm_mday = now.d.d; now_tm.tm_year = now.d.y - 1900; now_tm.tm_hour = now.t.h; now_tm.tm_min = now.t.m; now_tm.tm_sec = now.t.s; now_tm.tm_isdst = -1; now_t = mktime(&now_tm); now_t += (time_t)86400; /* add 1 day */ t = localtime(&now_t); range.hi.d.m = t->tm_mon + 1; range.hi.d.d = t->tm_mday; range.hi.d.y = t->tm_year + 1900; } return(datetimecmp(dt, range.lo) >= 0 && \ datetimecmp(dt, range.hi) <= 0); } /* * sizeInRange - returns 1 if sz is in range, 0 otherwise. * */ int inSizeRange(sz, range) Size sz; SizeRange range; { return(sizecmp(sz, range.lo) >= 0 && sizecmp(sz, range.hi) <= 0); } /* The following are functions related to IntRes and SizeRes */ struct IntRes *IntResCreate(void) { struct IntRes *iptr; iptr = (struct IntRes *) malloc(sizeof(struct IntRes)); assert(iptr != NULL); iptr->name = NULLSTR; iptr->value = -1; return(iptr); } int IntResValueGet(struct IntRes *head, char *name) { struct IntRes *iptr; for (iptr = head; iptr; iptr = iptr->nextptr) { if (strcmp(iptr->name, name) == 0) /* found a match */ { return(iptr->value); } } return(-1); } void IntResListPrint(struct IntRes *head, char *descr) { struct IntRes *iptr; for (iptr = head; iptr; iptr = iptr->nextptr) { printf("%s.%s = %d\n", descr, iptr->name, iptr->value); } } struct IntRes * IntResValuePut(struct IntRes *head, char *name, int value, void *pptr) { struct IntRes *iptr; for (iptr = head; iptr; iptr = iptr->nextptr) { if (strcmp(iptr->name, name) == 0) /* found a match */ { iptr->value = value; return(NULL); } } iptr = IntResCreate(); mallocTableAdd(iptr, pptr, 0); #ifdef DEBUG printf("Added IntRes ptr %x to mallocTable\n", iptr); #endif dynamic_strcpy(&iptr->name, name); varstrModPptr(iptr->name, pptr); iptr->value = value; iptr->nextptr = head; return(iptr); } void IntResListFree(struct IntRes *head) { struct IntRes *iptr, *tptr; tptr = NULL; for (iptr = head; iptr; iptr = tptr) { tptr = iptr->nextptr; varstrFree(iptr->name); mallocTableFree(iptr); } } static struct SizeRes *SizeResCreate(void) { struct SizeRes *iptr; iptr = (struct SizeRes *) malloc(sizeof(struct SizeRes)); assert(iptr != NULL); iptr->name = NULLSTR; iptr->value = strToSize("-1b"); return(iptr); } Size SizeResValueGet(head, name) struct SizeRes *head; char *name; { struct SizeRes *iptr; for (iptr = head; iptr; iptr = iptr->nextptr) { if (strcmp(iptr->name, name) == 0) /* found a match */ { return(iptr->value); } } return(strToSize("-1b")); } void SizeResListPrint(struct SizeRes *head, char *descr) { struct SizeRes *iptr; for (iptr = head; iptr; iptr = iptr->nextptr) { printf("%s.%s = ", descr, iptr->name); sizePrint(iptr->value, 1); printf("\n"); } } struct SizeRes *SizeResValuePut(head, name, value, pptr) struct SizeRes *head; char *name; Size value; void *pptr; { struct SizeRes *iptr; for (iptr = head; iptr; iptr = iptr->nextptr) { if (strcmp(iptr->name, name) == 0) /* found a match */ { iptr->value = value; return(NULL); } } iptr = SizeResCreate(); mallocTableAdd(iptr, pptr, 0); #ifdef DEBUG printf("Added SizeRes ptr %x to mallocTable\n", iptr); #endif dynamic_strcpy(&iptr->name, name); varstrModPptr(iptr->name, pptr); iptr->value = value; iptr->nextptr = head; return(iptr); } void SizeResListFree(struct SizeRes *head) { struct SizeRes *iptr, *tptr; tptr = NULL; for (iptr = head; iptr; iptr = tptr) { tptr = iptr->nextptr; varstrFree(iptr->name); mallocTableFree(iptr); } } static struct StringRes *StringResCreate(void) { struct StringRes *iptr; iptr = (struct StringRes *) malloc(sizeof(struct StringRes)); assert(iptr != NULL); iptr->name = NULLSTR; iptr->value = NULLSTR; return(iptr); } char * StringResValueGet(struct StringRes *head, char *name) { struct StringRes *iptr; for (iptr = head; iptr; iptr = iptr->nextptr) { if (strcmp(iptr->name, name) == 0) /* found a match */ { return(iptr->value); } } return(NULLSTR); } void StringResListPrint(struct StringRes *head, char *descr) { struct StringRes *iptr; for (iptr = head; iptr; iptr = iptr->nextptr) { printf("%s.%s = %s\n", descr, iptr->name, iptr->value); } } struct StringRes * StringResValuePut(struct StringRes *head, char *name, char *value, void *pptr) { struct StringRes *iptr; for (iptr = head; iptr; iptr = iptr->nextptr) { if (strcmp(iptr->name, name) == 0) /* found a match */ { dynamic_strcpy(&iptr->value, value); return(NULL); } } iptr = StringResCreate(); mallocTableAdd(iptr, pptr, 0); #ifdef DEBUG printf("Added StringRes ptr %x to mallocTable\n", iptr); #endif dynamic_strcpy(&iptr->name, name); varstrModPptr(iptr->name, pptr); dynamic_strcpy(&iptr->value, value); varstrModPptr(iptr->value, pptr); iptr->nextptr = head; return(iptr); } void StringResListFree(struct StringRes *head) { struct StringRes *iptr, *tptr; tptr = NULL; for (iptr = head; iptr; iptr = tptr) { tptr = iptr->nextptr; varstr2Free(iptr->name, iptr->value); mallocTableFree(iptr); } } DateTime strsecsToDateTime(val) char *val; { DateTime cdtime = { -1, -1, -1, 0, 0 , 0}; time_t secs; struct tm *timeptr; if (val == NULLSTR) { return(cdtime); } secs = (time_t) atol(val); timeptr = localtime(&secs); cdtime.t.h = timeptr->tm_hour; cdtime.t.m = timeptr->tm_min; cdtime.t.s = timeptr->tm_sec; cdtime.d.m = timeptr->tm_mon + 1; cdtime.d.d = timeptr->tm_mday; cdtime.d.y = timeptr->tm_year + 1900; return(cdtime); } int strToBool(char *val) { if (val == NULLSTR) { return(-1); } if (STRCMP(val, == , "True")) return(TRUE); else if (STRCMP(val, == , "False")) return(FALSE); else return(-1); }