home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / analg211.zip / utils.c < prev    next >
C/C++ Source or Header  |  1997-03-14  |  14KB  |  605 lines

  1. /*** analog 2.1 ***/
  2. /* Please read Readme.html, or http://www.statslab.cam.ac.uk/~sret1/analog/  */
  3.  
  4. /*** utils.c; lots of little functions to do odd little things ***/
  5.  
  6. #include "analhea2.h"
  7.  
  8. /* First, wildcard matching. */
  9.  
  10. flag matchq(char *string, char *pattern, flag whole)
  11. {        /* Match with no *'s, whole or start of string against pattern */
  12.   flag answer;
  13.  
  14.   for (answer = TRUE; answer == TRUE && *pattern != '\0' ; ) {
  15.     answer = (*string == *pattern || *pattern == '?') && (*string != '\0');
  16.     string++;
  17.     pattern++;
  18.   }
  19.  
  20.   if (whole && *string != '\0')
  21.     return(FALSE);
  22.  
  23.   return(answer);
  24. }
  25.  
  26. flag wildmatch(char *string, char *pattern, char **w1, char **w2)
  27. {   /* w1 and &w2 changed to reflect part of string represented by final *   */
  28.   char *c;
  29.   flag matched;
  30.   int len;
  31.   char tempstr[MAXSTRINGLENGTH];
  32.   flag tempflag;
  33.  
  34.   strcpy(tempstr, pattern);   /* so pattern won't be destroyed by strtok */
  35.  
  36.   if ((c = strrchr(tempstr, '*')) == NULL) {   /* no *'s */
  37.     *w1 = string;
  38.     *w2 = string;
  39.     return(matchq(string, pattern, TRUE));
  40.   }
  41.   else {
  42.     *w2 = string + MAX(strlen(string) - strlen(c + 1), 0);
  43.     if (!matchq(*w2, c + 1, TRUE))      /* if tail portions don't match */
  44.       return(0);
  45.     *c = '\0';   /* o/wise we'll end up matching the tail twice */
  46.     c = strtok(tempstr, "*");
  47.     if (pattern[0] == '*') {   /* don't need to match against beginning */
  48.       tempflag = ON;
  49.       *w1 = string;
  50.     }
  51.     else {
  52.       tempflag = OFF;
  53.       if (matchq(string, c, FALSE) == FALSE)
  54.     return(FALSE);    /* check first bit matches beginning of string */
  55.       *w1 = string + strlen(c); /* w1 measures where we're up to in string */
  56.       if (*w1 > *w2)
  57.     return(FALSE);   /* start and end of pattern overlapped in string */
  58.     }
  59.     if (tempflag && c == NULL)
  60.       return(TRUE);  /* this only occurs with patterns like "*nomorestars" */
  61.     else while (tempflag || ((c = strtok((char *)NULL, "*")) != NULL)) {
  62.       /* if tempflag, c is already set to after initial *  */
  63.       tempflag = OFF;
  64.       matched = FALSE;
  65.       len = strlen(c);
  66.       while (*w1 + len <= *w2 && matched == FALSE) {
  67.     if (matchq(*w1, c, FALSE) == TRUE)
  68.       matched = TRUE;
  69.     else
  70.       (*w1)++;
  71.       }
  72.       if (!matched)
  73.     return(FALSE);
  74.       else
  75.     *w1 += len;
  76.     }
  77.     return(TRUE);  /* if got this far, matched everything */
  78.   }
  79. }
  80.  
  81. int strtomonth(char month[4])  /* convert 3 letter month abbrev. to int */
  82. {
  83.   int monthno = ERR;
  84.  
  85.   switch (month[0]) {
  86.   case 'A':
  87.     switch (month[1]) {
  88.     case 'p':
  89.       monthno = 3;
  90.       break;
  91.     case 'u':
  92.       monthno = 7;
  93.       break;
  94.     }
  95.     break;
  96.     case 'D':
  97.     monthno = 11;
  98.       break;
  99.   case 'F':
  100.     monthno = 1;
  101.     break;
  102.     case 'J':
  103.     switch (month[1]) {
  104.     case 'a':
  105.       monthno = 0;
  106.       break;
  107.     case 'u':
  108.       switch (month[2]) {
  109.       case 'l':
  110.     monthno = 6;
  111.     break;
  112.       case 'n':
  113.     monthno = 5;
  114.     break;
  115.       }
  116.       break;
  117.     }
  118.     break;
  119.   case 'M':
  120.     switch (month[2]) {
  121.     case 'r':
  122.       monthno = 2;
  123.       break;
  124.     case 'y':
  125.       monthno = 4;
  126.       break;
  127.     }
  128.     break;
  129.   case 'N':
  130.     monthno = 10;
  131.     break;
  132.   case 'O':
  133.     monthno = 9;
  134.       break;
  135.   case 'S':
  136.     monthno = 8;
  137.     break;
  138.   }
  139.  
  140.   return(monthno);
  141.  
  142. }
  143.  
  144. int dayofdate(int date, int monthno, int year)  /* day of week of given date */
  145. {
  146.   extern int dateoffset[];
  147.  
  148.   int x;
  149.   x = dateoffset[monthno] + date + year + (year / 4) + 5 -
  150.     ISLEAPJF(monthno, year);
  151.   return(x % 7);
  152. }
  153.  
  154. int minsbetween(int date1, int monthno1, int year1, int hr1, int min1,
  155.         int date2, int monthno2, int year2, int hr2, int min2)
  156. {
  157.   extern int dateoffset[];
  158.  
  159.   int x, y;
  160.   x = dateoffset[monthno1] + date1 + year1 * 365 + (year1 / 4) -
  161.     ISLEAPJF(monthno1, year1);
  162.   y = dateoffset[monthno2] + date2 + year2 * 365 + (year2 / 4) -
  163.     ISLEAPJF(monthno2, year2);
  164.  
  165.   return((y - x) * 1440 + (hr2 - hr1) * 60 + (min2 - min1));
  166. }
  167.  
  168. long timecode(int date, int monthno, int year, int hr, int min)
  169. {   /* calculate a 'timecode', i.e. increasing function of time */
  170.  
  171.   return((year - 1990) * 535680 +       /* 60 * 24 * 31 * 12 */
  172.      monthno * 44640 +
  173.      date * 1440 +
  174.      hr * 60 +
  175.      min);
  176. }
  177.  
  178. struct timestruct startofweek(struct timestruct atime)
  179. {  /* given a time, what is the time at the start of that week? */
  180.  
  181.   extern int monthlength[];
  182.  
  183.   extern int weekbeginson;
  184.  
  185.   struct timestruct answer;
  186.   int day;
  187.   
  188.   day = dayofdate(atime.date, atime.monthno, atime.year);
  189.  
  190.   answer.date = atime.date - day + weekbeginson;
  191.            /* giving a weekbeginson-day in [date - 6, date + 6] */
  192.   if (answer.date > atime.date)
  193.     answer.date -= 7;
  194.   answer.monthno = atime.monthno;
  195.   answer.year = atime.year;
  196.  
  197.   if (answer.date <= 0) {
  198.     answer.monthno--;
  199.     if (answer.monthno == -1) {
  200.       answer.monthno = 11;
  201.       answer.year--;
  202.     }
  203.     answer.date = monthlength[answer.monthno] + answer.date +
  204.       ISLEAPFEB(answer.monthno, answer.year);
  205.   }
  206.  
  207.   answer.code = timecode(answer.date, answer.monthno, answer.year,
  208.              answer.hr = 0, answer.min = 0);
  209.  
  210.   return(answer);
  211.  
  212. }
  213.  
  214. FILE *fopenlog(char *name, char logtype[14], flag *ispipe)
  215. {             /* open a logfile with a particular name for reading */
  216. #ifndef NOPIPES
  217.   extern FILE *popen();
  218. #endif
  219.  
  220.   extern char *commandname;
  221. #ifndef NOPIPES
  222.   extern struct loglist *uncompresshead;
  223. #endif
  224.   extern flag warnq, anywarns, stdin_used;
  225.   extern int debug;
  226.  
  227.   FILE *f;
  228. #ifndef NOPIPES
  229.   struct loglist *uncompressp;
  230.   char *w1, *w2;
  231.   char command[MAXSTRINGLENGTH];
  232. #endif
  233.  
  234.   *ispipe = OFF;
  235.  
  236.   if (STREQ(name, "stdin") || STREQ(name, "-")) {
  237.     if (stdin_used) {
  238.       if (warnq) {
  239.     fprintf(stderr,
  240.         "%s: Warning: stdin already used; cannot use it as %s\n",
  241.         commandname, logtype);
  242.     anywarns = ON;
  243.       }
  244.     }
  245.     else {
  246.       f = stdin;
  247.       stdin_used = ON;
  248.       if (debug > 0)
  249.     fprintf(stderr, "F: Opening stdin as %s\n", logtype);
  250.     }
  251.   }
  252.   else {
  253. #ifdef VMS
  254.     f = fopen(name, "r", "shr=upd");
  255. #else
  256.     f = fopen(name, "r");
  257. #endif
  258.     if (f == NULL) {
  259.       if (warnq) {
  260.     fprintf(stderr, "%s: Warning: Failed to open %s %s: ignoring it\n",
  261.         commandname, logtype, name);
  262.     anywarns = ON;
  263.       }
  264.     }
  265.     else {
  266.       if (debug > 0)
  267.     fprintf(stderr, "F: Opening %s as %s\n", name, logtype);
  268. #ifndef NOPIPES
  269.       for (uncompressp = uncompresshead; uncompressp -> name[0] != '\0' &&
  270.        !(*ispipe); uncompressp = uncompressp -> next) {
  271.     if (wildmatch(name, uncompressp -> name, &w1, &w2)) {
  272.       fclose(f);
  273.       strcpy(command, uncompressp -> prefix);
  274.       strcat(command, " ");
  275.       strncat(command, name, MAXSTRINGLENGTH - strlen(command) - 1);
  276.       f = popen(command, "r");
  277.       *ispipe = ON;
  278.       if (debug > 0)
  279.         fprintf(stderr, "F:   Using %s to uncompress it\n",
  280.             uncompressp -> prefix);
  281.     }
  282.       }
  283. #endif
  284.     }
  285.   }
  286.  
  287.   return(f);
  288. }
  289.  
  290. int fcloselog(FILE *f, char *name, char logtype[14], flag ispipe)
  291. {     /* close it again */  /* logtype only used if NOPIPES off */
  292. #ifndef NOPIPES
  293.   extern int pclose();
  294. #endif
  295.  
  296.   extern int debug;
  297.  
  298. #ifndef NOPIPES
  299.   extern char *commandname;
  300.   extern flag warnq, anywarns;
  301. #endif
  302.  
  303.   int rc;
  304.  
  305.   if (debug > 0)
  306.     fprintf(stderr, "F: Closing %s\n", STREQ(name, "-")?"stdin":name);
  307.   if (!ispipe)
  308.     rc = fclose(f);    /* Not much can go wrong with fclose. I hope. */
  309. #ifndef NOPIPES
  310.   else if ((rc = pclose(f)) != 0 && warnq) {
  311.     fprintf(stderr, "%s: Warning: Problems uncompressing %s %s\n",
  312.         commandname, logtype, name);
  313.     anywarns = ON;
  314.   }
  315. #endif
  316.   return(rc);
  317. }
  318.  
  319. void int3printf(FILE *outf, int x, char sepchar, int fieldwidth)
  320.                     /* print +ve integer with separators every 3 digits */
  321. {                   /* assume fieldwidth is 0, or large enough */
  322.   extern int aq;
  323.  
  324.   int i = 1, len = 0;
  325.  
  326.   if (sepchar == '\0') {
  327.     if (fieldwidth == 0)
  328.       fprintf(outf, "%d", x);
  329.     else
  330.       fprintf(outf, "%*d", fieldwidth, x);
  331.   }
  332.  
  333.   else {
  334.     while (x / 1000 >= i) {   /* i * 1000 might overflow */
  335.       i *= 1000;     /* find how big x is, so we know where to start */
  336.       len += 4;
  337.     }
  338.  
  339.     if (fieldwidth == 0)
  340.       fprintf(outf, "%d", (x / i) % 1000);
  341.     else
  342.       fprintf(outf, "%*d", fieldwidth - len, (x / i) % 1000);
  343.                            /* now run down again, printing each clump */
  344.  
  345.     for ( i /= 1000; i >= 1; i /= 1000) {
  346.       if (aq == HTML)
  347.     htmlputc(sepchar, outf);
  348.       else
  349.     fprintf(outf, "%c", sepchar);
  350.       fprintf(outf, "%03d", (x / i) % 1000);
  351.     }
  352.   }
  353. }
  354.  
  355. void double3printf(FILE *outf, double x, char sepchar, int fieldwidth)
  356.                          /* the same, only with +ve INTEGER doubles */
  357. {
  358.   extern int aq;
  359.  
  360.   int i = 0;
  361.  
  362.   x += 0.1;   /* to make sure floors go in the right direction */
  363.  
  364.   if (x < 0.6) {
  365.     for (i = fieldwidth; i > 1; i--)
  366.       fprintf(outf, " ");
  367.     fprintf(outf, "0");
  368.   }
  369.  
  370.   else if (sepchar == '\0') {
  371.     if (fieldwidth == 0)
  372.       fprintf(outf, "%.0f", x);
  373.     else
  374.       fprintf(outf, "%*.0f", fieldwidth, x);
  375.   }
  376.  
  377.   else {
  378.  
  379.     while (x >= 1000) {
  380.       x /= 1000;
  381.       i++;
  382.     }
  383.  
  384.     if (i == 0) {
  385.       if (fieldwidth == 0)
  386.     fprintf(outf, "%d", (int)ROUND(x));
  387.       else
  388.     fprintf(outf, "%*d", fieldwidth - 4 * i, (int)ROUND(x));
  389.     }
  390.     else if (fieldwidth == 0)
  391.       fprintf(outf, "%d", (int)floor(x));
  392.     else
  393.       fprintf(outf, "%*d", fieldwidth - 4 * i, (int)floor(x));
  394.  
  395.     for ( ; i >= 1; i--) {
  396.       x -= (int)x;
  397.       x *= 1000;
  398.       if (aq == HTML)
  399.     htmlputc(sepchar, outf);
  400.       else
  401.     fprintf(outf, "%c", sepchar);
  402.       if (i == 1)
  403.     fprintf(outf, "%03d", (int)ROUND(x));
  404.       else
  405.     fprintf(outf, "%03d", (int)floor(x));
  406.     }
  407.   }
  408. }
  409.  
  410. void doublefprintf(FILE *outf, double x)
  411. {                 /* print a double in %f format without trailing zeros */
  412.   extern char decpoint;
  413.  
  414.   int prec = 0;
  415.   double d;
  416.  
  417.   /* first calculate how many decimal places we need */
  418.  
  419.   for (d = x - floor(x); d - floor(d + 0.000005) > 0.00001; d *= 10)
  420.     prec++;
  421.  
  422.   /* now print it */
  423.  
  424.   if (prec > 0) {
  425.     fprintf(outf, "%d", (int)floor(x));
  426.     fprintf(outf, "%c%0*d", decpoint, prec, (int)ROUND(d));
  427.   }
  428.   else
  429.     fprintf(outf, "%d", (int)ROUND(x));
  430. }
  431.  
  432. void *xmalloc(size_t size)
  433. {    /* the same as malloc, only checks for out of memory */
  434.  
  435.   extern char *commandname;
  436.   extern flag sq;
  437.  
  438.   void *answer;
  439.  
  440.   if ((answer = malloc(size)) == NULL) {
  441.     fprintf(stderr, "%s: Ran out of memory: cannot continue\n", commandname);
  442.     if (sq == ON) {
  443. #ifdef MAC
  444.       fprintf(stderr, "  Try allocating more memory or using approximate host counting.\n");
  445. #else
  446.       fprintf(stderr, "  Try turning hostname counting off or using approximate host counting.\n");
  447. #endif
  448.     }
  449.     exit(ERR);
  450.   }
  451.  
  452.   return(answer);
  453. }
  454.  
  455. void *xcalloc(size_t nelem, size_t elsize)
  456. {    /* ditto calloc */
  457.  
  458.   extern char *commandname;
  459.   extern flag sq;
  460.  
  461.   void *answer;
  462.  
  463.   if ((answer = calloc(nelem, elsize)) == NULL) {
  464.     fprintf(stderr, "%s: Ran out of memory: cannot continue\n", commandname);
  465.     if (sq == ON) {
  466. #ifdef MAC
  467.       fprintf(stderr, "  Try allocating more memory or using approximate host counting.\n");
  468. #else
  469.       fprintf(stderr, "  Try turning hostname counting off or using approximate host counting.\n");
  470. #endif
  471.     }
  472.     exit(ERR);
  473.   }
  474.  
  475.   return(answer);
  476. }
  477.  
  478. char *strtolower(char *string)
  479. {         /* convert a string to lower case */
  480.  
  481.   char *c;
  482.  
  483.   for (c = string ; *c != '\0'; c++)
  484.     *c = tolower(*c);
  485.  
  486.   return(string);
  487. }
  488.  
  489. flag strtolowerf(char *string)
  490. {         /* convert a string, return whether any changes required */
  491.  
  492.   char *c;
  493.   flag ans = FALSE;
  494.  
  495.   for (c = string ; *c != '\0'; c++) {
  496.     if (isupper(*c)) {
  497.       ans = TRUE;
  498.       *c = tolower(*c);
  499.     }
  500.   }
  501.  
  502.   return(ans);
  503. }
  504.  
  505. char *strtoupper(char *string)
  506. {         /* convert a string to upper case */
  507.  
  508.   char *c;
  509.  
  510.   for (c = string; *c != '\0'; c++)
  511.     *c = toupper(*c);
  512.  
  513.   return(string);
  514. }
  515.  
  516. int hoststrcmp(char *hostn1, char *hostn2)
  517. {   /* given two reversed hostnames, what is their "alphabetical" order? */
  518.  
  519.   char hostn1cpy[MAXSTRINGLENGTH], hostn2cpy[MAXSTRINGLENGTH];
  520.   char *part11, *part12, *part13, *part14, *part2;
  521.   int tempint1, tempint2;
  522.  
  523.   if (!isdigit(*hostn1)) {
  524.     if (isdigit(*hostn2))
  525.       return(-1);    /* all numbers come after all letters */
  526.     else
  527.       return(strcmp(hostn1, hostn2));   /* both non-numbers; usual alphabet */
  528.   }
  529.   else if (!isdigit(*hostn2))
  530.     return(1);
  531.   else  {
  532.     /* the difficult case; both numerical. Convert bits to numbers */
  533.     strcpy(hostn1cpy, hostn1);   /* because strtok destroys the string */
  534.     strcpy(hostn2cpy, hostn2);
  535.     part11 = strtok(hostn1cpy, ".");
  536.     part12 = strtok((char *)NULL, ".");
  537.     part13 = strtok((char *)NULL, ".");
  538.     part14 = strtok((char *)NULL, ".");
  539.  
  540.     part2 = strtok(hostn2cpy, ".");
  541.     tempint1 = atoi(part11);
  542.     tempint2 = atoi(part2);
  543.     if (tempint1 != tempint2)
  544.       return(tempint1 - tempint2);
  545.     else {
  546.       part2 = strtok((char *)NULL, ".");
  547.       if (part12 == NULL && part2 == NULL)
  548.     return(0);
  549.       else if (part12 == NULL)
  550.     return(-999);
  551.       else if (part2 == NULL)
  552.     return(999);
  553.       else {
  554.     tempint1 = atoi(part12);
  555.     tempint2 = atoi(part2);
  556.     if (tempint1 != tempint2)
  557.       return(tempint1 - tempint2);
  558.     else {
  559.       part2 = strtok((char *)NULL, ".");
  560.       if (part13 == NULL && part2 == NULL)
  561.         return(0);
  562.       else if (part13 == NULL)
  563.         return(-999);
  564.       else if (part2 == NULL)
  565.         return(999);
  566.       else {
  567.         tempint1 = atoi(part13);
  568.         tempint2 = atoi(part2);
  569.         if (tempint1 != tempint2)
  570.           return(tempint1 - tempint2);
  571.         else {
  572.           part2 = strtok((char *)NULL, ".");
  573.           if (part14 == NULL && part2 == NULL)
  574.         return(0);
  575.           else if (part14 == NULL)
  576.         return(-999);
  577.           else if (part2 == NULL)
  578.         return(999);
  579.           else {
  580.         tempint1 = atoi(part14);
  581.         tempint2 = atoi(part2);
  582.         if (tempint1 != tempint2)
  583.           return(tempint1 - tempint2);
  584.         else
  585.           return(0);
  586.           }
  587.         }
  588.       }
  589.     }
  590.       }
  591.     }
  592.   }
  593. }
  594.  
  595. /* Next, whether a host name is a numeric IP address */
  596. /* Actually we only check whether it consists only of digits & dots */
  597.  
  598. flag isnumeric(char *name)
  599. {
  600.   for ( ; *name != '\0'; name++)
  601.     if (!isdigit(*name) && *name != '.')
  602.       return(FALSE);
  603.   return(TRUE);
  604. }
  605.