This is utils.c in view mode; [Download] [Up]
/*** analog 1.9beta ***/ /* Please read Readme.html, or http://www.statslab.cam.ac.uk/~sret1/analog/ */ /*** utils.c; lots of little functions to do odd little things ***/ #include "analhea2.h" /* First, wildcard matching. This is restricted to at most one * (but any ?s). NB argument order and return value different from HP/UX fnmatch() */ flag matchq(char *string, char *pattern, size_t n) { /* first, match with no *'s, up to n characters */ flag answer; for(answer = TRUE; answer == TRUE && (*string != '\0' || *pattern != '\0') && n > 0; n--) { answer = (*string == *pattern || *pattern == '?'); string++; pattern++; } return(answer); } flag wildmatch(char *string, char *pattern, char **w1, char **w2) { /* w1 and w2 are changed to reflect part of string represented by * */ char *c; flag answer; if ((c = strchr(pattern, '*')) == NULL) { *w1 = string; *w2 = string; return(matchq(string, pattern, INFINITY)); } else { *c = '\0'; *w1 = string + strlen(pattern); *w2 = string + MAX(strlen(string) - strlen(c + 1), 0); answer = (matchq(string, pattern, strlen(pattern))) && (matchq(*w2, c + 1, INFINITY)); *c = '*'; return(answer); } } int strtomonth(char month[3]) /* convert 3 letter month abbrev. to int */ { int monthno = ERR; switch (month[0]) { case 'A': switch (month[1]) { case 'p': monthno = 3; break; case 'u': monthno = 7; break; } break; case 'D': monthno = 11; break; case 'F': monthno = 1; break; case 'J': switch (month[1]) { case 'a': monthno = 0; break; case 'u': switch (month[2]) { case 'l': monthno = 6; break; case 'n': monthno = 5; break; } break; } break; case 'M': switch (month[2]) { case 'r': monthno = 2; break; case 'y': monthno = 4; break; } break; case 'N': monthno = 10; break; case 'O': monthno = 9; break; case 'S': monthno = 8; break; } return(monthno); } int dayofdate(int date, int monthno, int year) /* day of week of given date */ { extern int dateoffset[]; int x; x = dateoffset[monthno] + date + year + (year / 4) + 5 - ISLEAPJF(monthno, year); return(x % 7); } int minsbetween(int date1, int monthno1, int year1, int hr1, int min1, int date2, int monthno2, int year2, int hr2, int min2) { extern int dateoffset[]; int x, y; x = dateoffset[monthno1] + date1 + year1 * 365 + (year1 / 4) - ISLEAPJF(monthno1, year1); y = dateoffset[monthno2] + date2 + year2 * 365 + (year2 / 4) - ISLEAPJF(monthno2, year2); return((y - x) * 1440 + (hr2 - hr1) * 60 + (min2 - min1)); } long timecode(int date, int monthno, int year, int hr, int min) { /* calculate a 'timecode', i.e. increasing function of time */ return((year - 1990) * 535680 + /* 60 * 24 * 31 * 12 */ monthno * 44640 + date * 1440 + hr * 60 + min); } struct timestruct startofweek(struct timestruct atime) { /* given a time, what is the time at the start of that week? */ extern int monthlength[]; extern int weekbeginson; struct timestruct answer; int day; day = dayofdate(atime.date, atime.monthno, atime.year); answer.date = atime.date - day + weekbeginson; /* giving a weekbeginson-day in [date - 6, date + 6] */ if (answer.date > atime.date) answer.date -= 7; answer.monthno = atime.monthno; answer.year = atime.year; if (answer.date <= 0) { answer.monthno--; if (answer.monthno == -1) { answer.monthno = 11; answer.year--; } answer.date = monthlength[answer.monthno] + answer.date + ISLEAPFEB(answer.monthno, answer.year); } answer.code = timecode(answer.date, answer.monthno, answer.year, answer.hr = 0, answer.min = 0); return(answer); } FILE *fopenlog(char *name, char logtype[12], flag *ispipe) { /* open a logfile with a particular name for reading */ extern char commandname[]; extern struct loglist *uncompresshead; extern flag warnq; FILE *f; struct loglist *uncompressp; char *w1, *w2; char command[MAXSTRINGLENGTH]; *ispipe = OFF; if (STREQ(name, "stdin")) f = stdin; else { f = fopen(name, "r"); if (f == NULL) { if (warnq) fprintf(stderr, "%s: Warning: Failed to open %s %s: ignoring it\n", commandname, logtype, name); } else for (uncompressp = uncompresshead; uncompressp -> name[0] != '\0' && !(*ispipe); uncompressp = uncompressp -> next) { if (wildmatch(name, uncompressp -> name, &w1, &w2)) { fclose(f); strcpy(command, uncompressp -> prefix); strcat(command, " "); strcat(command, name); f = popen(command, "r"); *ispipe = ON; } } } return(f); } int fcloselog(FILE *f, char *name, char logtype[12], flag ispipe) { /* close it again */ extern char commandname[]; extern flag warnq; int rc; if (!ispipe) rc = fclose(f); /* Not much can go wrong with fclose. I hope. */ else if ((rc = pclose(f)) != 0 && warnq) fprintf(stderr, "%s: Warning: Problems uncompressing %s %s\n", commandname, logtype, name); return(rc); } void int3printf(FILE *outf, int x) /* print +ve integer with separators every 3 digits */ { extern char sepchar; int i = 1; if (sepchar == '\0') fprintf(outf, "%d", x); else { while (x / 1000 >= i) /* i * 1000 might overflow */ i *= 1000; /* find how big x is, so we know where to start */ fprintf(outf, "%d", (x / i) % 1000); /* now run down again, printing each clump */ for ( i /= 1000; i >= 1; i /= 1000) fprintf(outf, "%c%03d", sepchar, (x / i) % 1000); } } void double3printf(FILE *outf, double x) /* the same, only with +ve integer doubles */ { extern char sepchar; int i = 0; if (x < 0.5) fprintf(outf, "0"); else if (sepchar == '\0') fprintf(outf, "%.0f", x); else { while (x >= 1000) { x /= 1000; i++; } fprintf(outf, "%d", (int)ROUND(x)); for ( ; i >= 1; i--) { x -= (int)x; x *= 1000; fprintf(outf, "%c%03d", sepchar, (int)ROUND(x)); } } } void doublefprintf(FILE *outf, double x) { /* print a double in %f format without trailing zeros */ int prec; double d; /* first calculate how many decimal places we need */ d = x; for (prec = 0; d - floor(d + 0.000005) > 0.00001; prec++) d *= 10; /* now print it */ fprintf(outf, "%.*f", prec, x); } void *xmalloc(size_t size) { /* the same as malloc, only checks for out of memory */ extern char commandname[]; extern flag sq; void *answer; if ((answer = malloc(size)) == NULL) { fprintf(stderr, "%s: Ran out of memory: cannot continue\n", commandname); if (sq == ON) fprintf(stderr, " Try turning hostname counting off or using approximate host counting"); exit(ERR); } else return(answer); } void *xcalloc(int nelem, int elsize) { /* ditto calloc */ extern char commandname[]; extern flag sq; void *answer; if ((answer = calloc((size_t)nelem, (size_t)elsize)) == NULL) { fprintf(stderr, "%s: Ran out of memory: cannot continue\n", commandname); if (sq == ON) fprintf(stderr, " Try turning hostname counting off or using approximate host counting"); exit(ERR); } else return(answer); } char *strtolower(char *string) { /* convert a string to lower case */ char *c; for (c = string; *c != '\0'; c++) *c = tolower(*c); return(string); } char *strtoupper(char *string) { /* convert a string to upper case */ char *c; for (c = string; *c != '\0'; c++) *c = toupper(*c); return(string); } int magicno(char *string, int base) { /* convert a string to a magic number (using c_i.2^i mod b) */ int answer; int i; answer = 0; for (i = 0; string[i] != '\0'; i++) { answer += answer + string[i]; if (answer < 0) answer = -answer; while (answer >= base) answer -= base; } return(answer); } int hoststrcmp(char *hostn1, char *hostn2) { /* given two reversed hostnames, what is their "alphabetical" order? */ char hostn1cpy[MAXSTRINGLENGTH], hostn2cpy[MAXSTRINGLENGTH]; char *part11, *part12, *part13, *part14, *part2; int tempint1, tempint2; if (!isdigit(*hostn1)) { if (isdigit(*hostn2)) return(-1); /* all numbers come after all letters */ else return(strcmp(hostn1, hostn2)); /* both non-numbers; usual alphabet */ } else if (!isdigit(*hostn2)) return(1); else { /* the difficult case; both numerical. Convert bits to numbers */ strcpy(hostn1cpy, hostn1); /* because strtok destroys the string */ strcpy(hostn2cpy, hostn2); part11 = strtok(hostn1cpy, "."); part12 = strtok((char *)NULL, "."); part13 = strtok((char *)NULL, "."); part14 = strtok((char *)NULL, "."); part2 = strtok(hostn2cpy, "."); tempint1 = atoi(part11); tempint2 = atoi(part2); if (tempint1 != tempint2) return(tempint1 - tempint2); else { part2 = strtok((char *)NULL, "."); if (part12 == NULL && part2 == NULL) return(0); else if (part12 == NULL) return(-999); else if (part2 == NULL) return(999); else { tempint1 = atoi(part12); tempint2 = atoi(part2); if (tempint1 != tempint2) return(tempint1 - tempint2); else { part2 = strtok((char *)NULL, "."); if (part13 == NULL && part2 == NULL) return(0); else if (part13 == NULL) return(-999); else if (part2 == NULL) return(999); else { tempint1 = atoi(part13); tempint2 = atoi(part2); if (tempint1 != tempint2) return(tempint1 - tempint2); else { part2 = strtok((char *)NULL, "."); if (part14 == NULL && part2 == NULL) return(0); else if (part14 == NULL) return(-999); else if (part2 == NULL) return(999); else { tempint1 = atoi(part14); tempint2 = atoi(part2); if (tempint1 != tempint2) return(tempint1 - tempint2); else return(0); } } } } } } } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.