This is utils.c in view mode; [Download] [Up]
/*** analog 1.93beta ***/ /* 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. */ flag matchq(char *string, char *pattern, flag whole) { /* Match with no *'s, whole or start of string against pattern */ flag answer; for (answer = TRUE; answer == TRUE && *pattern != '\0' ; ) { answer = (*string == *pattern || *pattern == '?') && (*string != '\0'); string++; pattern++; } if (whole && *string != '\0') return(FALSE); return(answer); } flag wildmatch(char *string, char *pattern, char **w1, char **w2) { /* w1 and &w2 changed to reflect part of string represented by final * */ char *c; flag matched; int len; char tempstr[MAXSTRINGLENGTH]; flag tempflag; strcpy(tempstr, pattern); /* so pattern won't be destroyed by strtok */ if ((c = strrchr(tempstr, '*')) == NULL) { /* no *'s */ *w1 = string; *w2 = string; return(matchq(string, pattern, TRUE)); } else { *w2 = string + MAX(strlen(string) - strlen(c + 1), 0); if (!matchq(*w2, c + 1, TRUE)) /* if tail portions don't match */ return(0); *c = '\0'; /* o/wise we'll end up matching the tail twice */ c = strtok(tempstr, "*"); if (pattern[0] == '*') { /* don't need to match against beginning */ tempflag = ON; *w1 = string; } else { tempflag = OFF; if (matchq(string, c, FALSE) == FALSE) return(FALSE); /* check first bit matches beginning of string */ *w1 = string + strlen(c); /* w1 measures where we're up to in string */ if (*w1 > *w2) return(FALSE); /* start and end of pattern overlapped in string */ } if (tempflag && c == NULL) return(TRUE); /* this only occurs with patterns like "*nomorestars" */ else while (tempflag || ((c = strtok((char *)NULL, "*")) != NULL)) { /* if tempflag, c is already set to after initial * */ tempflag = OFF; matched = FALSE; len = strlen(c); while (*w1 + len <= *w2 && matched == FALSE) { if (matchq(*w1, c, FALSE) == TRUE) matched = TRUE; else (*w1)++; } if (!matched) return(FALSE); else *w1 += len; } return(TRUE); /* if got this far, matched everything */ } } int strtomonth(char month[4]) /* 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 */ #ifndef NOPIPES extern FILE *popen(); #endif extern char *commandname; #ifndef NOPIPES extern struct loglist *uncompresshead; #endif extern flag warnq, anywarns, stdin_used; extern int debug; FILE *f; #ifndef NOPIPES struct loglist *uncompressp; char *w1, *w2; char command[MAXSTRINGLENGTH]; #endif *ispipe = OFF; if (STREQ(name, "stdin") || STREQ(name, "-")) { if (stdin_used) { if (warnq) { fprintf(stderr, "%s: Warning: stdin already used; cannot use it as %s\n", commandname, logtype); anywarns = ON; } } else { f = stdin; stdin_used = ON; if (debug > 0) fprintf(stderr, "F: Opening stdin as %s\n", logtype); } } else { #ifdef VMS f = fopen(name, "r", "shr=upd"); #else f = fopen(name, "r"); #endif if (f == NULL) { if (warnq) { fprintf(stderr, "%s: Warning: Failed to open %s %s: ignoring it\n", commandname, logtype, name); anywarns = ON; } } else { if (debug > 0) fprintf(stderr, "F: Opening %s as %s\n", name, logtype); #ifndef NOPIPES 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, " "); strncat(command, name, MAXSTRINGLENGTH - strlen(command) - 1); f = popen(command, "r"); *ispipe = ON; if (debug > 0) fprintf(stderr, "F: Using %s to uncompress it\n", uncompressp -> prefix); } } #endif } } return(f); } int fcloselog(FILE *f, char *name, char logtype[12], flag ispipe) { /* close it again */ /* logtype only used if NOPIPES off */ extern int pclose(); extern int debug; #ifndef NOPIPES extern char *commandname; extern flag warnq, anywarns; #endif int rc; if (debug > 0) fprintf(stderr, "F: Closing %s\n", STREQ(name, "-")?"stdin":name); if (!ispipe) rc = fclose(f); /* Not much can go wrong with fclose. I hope. */ #ifndef NOPIPES else if ((rc = pclose(f)) != 0 && warnq) { fprintf(stderr, "%s: Warning: Problems uncompressing %s %s\n", commandname, logtype, name); anywarns = ON; } #endif return(rc); } void int3printf(FILE *outf, int x, char sepchar, int fieldwidth) /* print +ve integer with separators every 3 digits */ { /* assume fieldwidth is 0, or large enough */ extern int aq; int i = 1, len = 0; if (sepchar == '\0') { if (fieldwidth == 0) fprintf(outf, "%d", x); else fprintf(outf, "%*d", fieldwidth, x); } else { while (x / 1000 >= i) { /* i * 1000 might overflow */ i *= 1000; /* find how big x is, so we know where to start */ len += 4; } if (fieldwidth == 0) fprintf(outf, "%d", (x / i) % 1000); else fprintf(outf, "%*d", fieldwidth - len, (x / i) % 1000); /* now run down again, printing each clump */ for ( i /= 1000; i >= 1; i /= 1000) { if (aq == HTML) htmlputc(sepchar, outf); else fprintf(outf, "%c", sepchar); fprintf(outf, "%03d", (x / i) % 1000); } } } void double3printf(FILE *outf, double x, char sepchar, int fieldwidth) /* the same, only with +ve INTEGER doubles */ { extern int aq; int i = 0; x += 0.1; /* to make sure floors go in the right direction */ if (x < 0.6) { for (i = fieldwidth; i > 1; i--) fprintf(outf, " "); fprintf(outf, "0"); } else if (sepchar == '\0') { if (fieldwidth == 0) fprintf(outf, "%.0f", x); else fprintf(outf, "%*.0f", fieldwidth, x); } else { while (x >= 1000) { x /= 1000; i++; } if (i == 0) { if (fieldwidth == 0) fprintf(outf, "%d", (int)ROUND(x)); else fprintf(outf, "%*d", fieldwidth - 4 * i, (int)ROUND(x)); } else if (fieldwidth == 0) fprintf(outf, "%d", (int)floor(x)); else fprintf(outf, "%*d", fieldwidth - 4 * i, (int)floor(x)); for ( ; i >= 1; i--) { x -= (int)x; x *= 1000; if (aq == HTML) htmlputc(sepchar, outf); else fprintf(outf, "%c", sepchar); if (i == 1) fprintf(outf, "%03d", (int)ROUND(x)); else fprintf(outf, "%03d", (int)floor(x)); } } } void doublefprintf(FILE *outf, double x) { /* print a double in %f format without trailing zeros */ extern char decpoint; int prec = 0; double d; /* first calculate how many decimal places we need */ for (d = x - floor(x); d - floor(d + 0.000005) > 0.00001; d *= 10) prec++; /* now print it */ if (prec > 0) { fprintf(outf, "%d", (int)floor(x)); fprintf(outf, "%c%0*d", decpoint, prec, (int)ROUND(d)); } else fprintf(outf, "%d", (int)ROUND(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); } return(answer); } void *xcalloc(size_t nelem, size_t elsize) { /* ditto calloc */ extern char *commandname; extern flag sq; void *answer; if ((answer = calloc(nelem, 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); } 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); } flag strtolowerf(char *string) { /* convert a string, return whether any changes required */ char *c; flag ans = FALSE; for (c = string ; *c != '\0'; c++) { if (isupper(*c)) { ans = TRUE; *c = tolower(*c); } } return(ans); } char *strtoupper(char *string) { /* convert a string to upper case */ char *c; for (c = string; *c != '\0'; c++) *c = toupper(*c); return(string); } 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); } } } } } } } } /* Next, whether a host name is a numeric IP address */ /* Actually we only check whether it consists only of digits & dots */ flag isnumeric(char *name) { for ( ; *name != '\0'; name++) if (!isdigit(*name) && *name != '.') return(FALSE); return(TRUE); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.