ftp.nice.ch/pub/next/unix/network/www/analog.NIHS.bs.gnutar.gz#/analog/utils.c

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.