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.