/*** analog 1.2 ***/ /* Please read Readme.html, or http://www.statslab.cam.ac.uk/~sret1/analog/ */ /*** utilities.c; lots of little functions to do odd little things ***/ #include "analhead2.h" int strtomonth(char month[3]) /* convert 3 letter month abbrev. to int */ { int monthno; 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 - (monthno <= 1 && year % 4 == 0); /* every fourth year until 2099 is a leap 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) - (monthno1 <= 1 && year1 % 4 == 0); y = dateoffset[monthno2] + date2 + year2 * 365 + (year2 / 4) - (monthno2 <= 1 && year2 % 4 == 0); 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 + (answer.monthno == 1 && answer.year % 4 == 0); } answer.code = timecode(answer.date, answer.monthno, answer.year, answer.hr = 0, answer.min = 0); return(answer); } void int3printf(FILE *outf, int x) /* print +ve integer with separators every 3 digits */ { extern char sepchar; int i = 1; 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 { while (x >= 1000) { x /= 1000; i++; } fprintf(outf, "%.0f", x - 0.49999); for ( ; i >= 1; i--) { x -= (int)x; x *= 1000; fprintf(outf, "%c%03.0f", sepchar, x - 0.49999); } } } 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 m) */ 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(NULL, "."); part13 = strtok(NULL, "."); part14 = strtok(NULL, "."); part2 = strtok(hostn2cpy, "."); tempint1 = atoi(part11); tempint2 = atoi(part2); if (tempint1 != tempint2) return(tempint1 - tempint2); else { part2 = strtok(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(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(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); } } } } } } } }