home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume4 / rolodex / part3 / toolsdir / ctools.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-30  |  19.9 KB  |  995 lines

  1. /* -*- Mode: C; Package: (CTOOLS C) -*- */
  2.  
  3. #include <ctype.h>
  4. #include <stdio.h>
  5.  
  6. #ifdef BSD42
  7. #include <strings.h>
  8. #endif
  9.  
  10. #include "ctools.h"
  11.  
  12. /* miscellaneous fairly primitive routines that deal with characters, */
  13. /* strings, memory, simple input and pathnames. */
  14.  
  15.  
  16. /* Author:  JP Massar */
  17. /* Thinking Machines Corporation */
  18.  
  19. /* Included routines:
  20.  
  21.    emalloc
  22.    anewstr
  23.    
  24.    copy
  25.    fill
  26.    
  27.    to_upper_if_lower
  28.    to_lower_if_upper
  29.    
  30.    buffconcat
  31.    nbuffconcat
  32.    
  33.    slcompare
  34.    slge_compare
  35.    nocase_compare
  36.    
  37.    strfind
  38.    strncfind
  39.    strsearch
  40.    strncsearch
  41.    
  42.    yes_or_no_check
  43.    
  44.    remove_excess_blanks
  45.    ip_string_trim
  46.    string_trim
  47.    string_upcase
  48.    string_downcase
  49.    
  50.    all_digits
  51.    all_whitespace
  52.    all_uppercase
  53.    all_lowercase
  54.    all_alphabetic
  55.    all_alphanumeric
  56.    all_ascii
  57.    
  58.    str_to_pos_int
  59.    
  60.    sreverse
  61.    ip_sreverse
  62.         
  63.    temp_path
  64.    perm_path
  65.    make_path_numeric_extension
  66.    make_path
  67.    just_filename
  68.    
  69.    read_yes_or_no
  70.    getline
  71.    getlines
  72.    ngetlines
  73.    getfile
  74.    ngetfile
  75.    read_file_into_buffer
  76.    efopen
  77.  
  78.    check_int
  79.    check_string
  80.    
  81. */
  82.    
  83.  
  84. extern char *malloc();
  85.  
  86.  
  87. char *emalloc (space) int space;
  88.  
  89. /* allocate 'space' bytes, die if we have run out of memory. */
  90.  
  91. {
  92.   char *rval;        
  93.   if (space < 0) {
  94.      fprintf(stderr,"Fatal error: argument to emalloc < 0\n");
  95.      exit(-1);
  96.   }
  97.   if (0 == (rval = malloc((unsigned) space))) {
  98.      fprintf(stderr,"Fatal error:  No more memory\n");
  99.      exit(-1);
  100.   }
  101.   return(rval);
  102. }  
  103.  
  104.  
  105. char *anewstr (astring) char *astring;
  106.  
  107. /* allocate space for and then copy a string.  Returns pointer to */
  108. /* new string. */
  109.  
  110. {        
  111.   char *newstr;
  112.   newstr = emalloc(strlen(astring)+1);
  113.   strcpy(newstr,astring);
  114.   return(newstr);
  115. }
  116.  
  117.  
  118. copy (dest,src,n)
  119.  
  120.   /* copy n bytes */
  121.  
  122.   register char *dest,*src;
  123.   register int n;
  124.  
  125.   { register int j = 0;
  126.     while (j++ < n) *dest++ = *src++; 
  127.   }
  128.  
  129.  
  130. fill (addr,ch,n)
  131.  
  132.   /* fill n sequential bytes with 'ch' */
  133.  
  134.   register char *addr;
  135.   register char ch;
  136.   register int n;
  137.   
  138.   { register int j = 0;
  139.     while (j++ < n) *addr++ = ch;
  140.   }
  141.  
  142.  
  143. to_upper_if_lower (ch)
  144.  
  145.   char ch;
  146.  
  147.   { return(islower(ch) ? toupper(ch) : ch); }
  148.  
  149.  
  150. to_lower_if_upper (ch)
  151.  
  152.   char ch;
  153.  
  154.   { return(isupper(ch) ? tolower(ch) : ch); }
  155.  
  156.  
  157. buffconcat (buffer,s1,s2) 
  158.  
  159.   /* concatenate two null terminated strings into a buffer. */
  160.  
  161.   char *buffer, *s1, *s2;
  162.   
  163.   { while (*s1 != '\0') *buffer++ = *s1++;
  164.     while (*s2 != '\0') *buffer++ = *s2++;
  165.     *buffer = '\0';
  166.   }
  167.  
  168.  
  169. nbuffconcat (buffer,n,s1,s2,s3,s4,s5,s6)
  170.  
  171.   /* concatenates up to 6 strings into a buffer.  Returns -1 if n */
  172.   /* is not reasonable, otherwise returns 0. */
  173.  
  174.   char *buffer;
  175.   int n;
  176.   char *s1,*s2,*s3,*s4,*s5,*s6;
  177.  
  178. {
  179.   register char *b;
  180.   register char *s;
  181.   int i;
  182.   b = buffer;
  183.   if (n < 1 || n > 6) return(-1);
  184.   for (i = 1; i <= 6; i++) {
  185.       if (i > n) break;
  186.       switch (i) {
  187.         case 1 : s = s1; break;
  188.         case 2 : s = s2; break;
  189.         case 3 : s = s3; break;
  190.         case 4 : s = s4; break;
  191.         case 5 : s = s5; break;
  192.         case 6 : s = s6; break;
  193.       }
  194.       while (*s != '\0') *b++ = *s++;
  195.   }
  196.   *b = '\0';
  197.   return(0);
  198. }
  199.  
  200.  
  201. slcompare (s1,l1,s2,l2)
  202.  
  203.   /* compare strings with possible nulls in them given their lengths */
  204.   /* only returns EQUAL (0) or NOT EQUAL (-1) */
  205.  
  206.   char *s1;
  207.   int l1;
  208.   char *s2;
  209.   int l2;
  210.  
  211.   { int j;
  212.     if (l1 != l2) return(-1);
  213.     j = 0;
  214.     while (j++ < l1) 
  215.       if (*s1++ != *s2++) return(-1);
  216.     return(0);
  217.   }
  218.  
  219.   
  220. slge_compare (s1,l1,s2,l2)
  221.  
  222.   /* returns -1 if s1 < s2; 1 if s2 < s1; 0 if s1 = s2 */
  223.   /* ignores nulls in the strings */
  224.  
  225.   char *s1;
  226.   int l1;
  227.   char *s2;
  228.   int l2;
  229.  
  230.   { int j,len;
  231.     j = 0;
  232.     len = l2 > l1 ? l1 : l2;
  233.     while (j++ < len) {
  234.       if (*s1 != *s2) 
  235.          return((*s1 < *s2) ? -1 : 1);
  236.       s1++;   
  237.       s2++;
  238.     }  
  239.     return((l2 == l1) ? 0 : ((l1 < l2) ? -1 : 1));
  240.   }
  241.  
  242. nocase_compare (s1,l1,s2,l2)
  243.  
  244.   /* treats nulls as normal characters.  Returns same as slge_compare */
  245.  
  246.   char *s1;
  247.   int l1;
  248.   char *s2;
  249.   int l2;
  250.  
  251.   { int j,len,ch1,ch2;
  252.     j = 0;
  253.     len = l2 > l1 ? l1 : l2;
  254.     while (j++ < len) {
  255.       ch1 = to_upper_if_lower(*s1++);
  256.       ch2 = to_upper_if_lower(*s2++);
  257.       if (ch1 != ch2) {
  258.          return((ch1 < ch2) ? -1 : 1);
  259.       }
  260.     }  
  261.     return((l2 == l1) ? 0 : ((l1 < l2) ? -1 : 1));
  262.   }
  263.  
  264.  
  265. char *strfind(s1,s2,fast)  
  266.   
  267.   register char *s1;
  268.   char *s2;
  269.   Bool fast;
  270.   
  271. {  
  272.   register int len1,len2;
  273.   len2 = strlen(s2);
  274.   if (fast) {
  275.      while (*s1 != '\0')
  276.        if (0 == strncmp(s1++,s2,len2)) return(s1-1);
  277.   }  
  278.   else {
  279.      len1 = strlen(s1);
  280.      while (len1 >= len2) {
  281.        if (0 == strncmp(s1++,s2,len2)) return(s1-1);
  282.        len1--;
  283.      }
  284.   }
  285.   return(0);
  286. }     
  287.  
  288.  
  289. char *strncfind(s1,s2,fast)
  290.  
  291.   register char *s1;
  292.   char *s2;
  293.   Bool fast;
  294.   
  295. {  
  296.   register int len1,len2;
  297.   len2 = strlen(s2);
  298.   if (fast) {
  299.      while (*s1 != '\0')
  300.        if (0 == nocase_compare(s1++,len2,s2,len2)) return(s1-1);
  301.   }
  302.   else {
  303.      len1 = strlen(s1);
  304.      while (len1 >= len2) {
  305.        if (0 == nocase_compare(s1++,len2,s2,len2)) return(s1-1);
  306.        len1--;
  307.      }
  308.   }
  309.   return(0);
  310. }  
  311.  
  312.   
  313. char *strsearch(s1,s1len,s2,s2len)
  314.  
  315.   /* do a substring search without noticing nulls */
  316.   /* finds s2 in s1, returns pointer into s1 or 0 */
  317.  
  318.   register char *s1, *s2;
  319.   register int s1len,s2len;
  320.   
  321.   {  register char *pc;
  322.      register char *bound;
  323.      register char *pctemp;
  324.      register char *s2temp;
  325.      register int j;
  326.  
  327.      bound = s1 + s1len - s2len;
  328.      for (pc = s1; pc <= bound; pc++) {
  329.          pctemp = pc;
  330.          s2temp = s2;
  331.          for (j = 0; j < s2len; j++)
  332.              if (*pctemp++ != *s2temp++) goto not_here;
  333.          return(pc);       
  334.          not_here :
  335.          continue;
  336.      }    
  337.      return(0);
  338. }
  339.  
  340.  
  341. char *strncsearch(s1,s1len,s2,s2len)
  342.  
  343.   /* do a substring search without noticing nulls */
  344.   /* finds s2 in s1, returns pointer into s1 or 0 */
  345.   /* case independent */
  346.  
  347.   register char *s1, *s2;
  348.   register int s1len,s2len;
  349.   
  350.   {  register char *pc;
  351.      register char *bound;
  352.      register char *pctemp;
  353.      register char *s2temp;
  354.      register int j;
  355.      char ch1, ch2;
  356.  
  357.      bound = s1 + s1len - s2len;
  358.      for (pc = s1; pc <= bound; pc++) {
  359.          pctemp = pc;
  360.          s2temp = s2;
  361.          for (j = 0; j < s2len; j++) {
  362.              ch1 = *pctemp++;
  363.              ch2 = *s2temp++;
  364.              if (to_upper_if_lower(ch1) != to_upper_if_lower(ch2))
  365.                 goto not_here;
  366.          }
  367.          return(pc);       
  368.          not_here :
  369.          continue;
  370.      }    
  371.      return(0);
  372. }
  373.  
  374.  
  375. int remove_excess_blanks (newstring,oldstring) 
  376.  
  377.   /* it is assumed that newstring is as long as oldstring if necessary */
  378.  
  379.   char *newstring,*oldstring;
  380.  
  381. {
  382.   int count = 0;
  383.   int space_found = 0;
  384.  
  385.   /* skip over all blanks at beginning */
  386.   
  387.   if (*oldstring == ' ') {
  388.      while (*oldstring == ' ') oldstring++;
  389.   }
  390.  
  391.   while (*oldstring != '\0') {
  392.         if (space_found && *oldstring == ' ') {
  393.            oldstring++;
  394.            continue;
  395.         }
  396.         space_found = (*oldstring == ' ');
  397.         *newstring++ = *oldstring++;
  398.         count++;
  399.   }
  400.  
  401.   *newstring = '\0';
  402.   if (count > 0 && *(newstring - 1) == ' ') {
  403.      count--;
  404.      *(newstring - 1) = '\0';
  405.   }
  406.  
  407.   return(count);
  408.  
  409. }
  410.  
  411. int ip_string_trim (oldstring,trimchars,pretrim,posttrim)
  412.  
  413.   char *oldstring, *trimchars;
  414.   Bool pretrim,posttrim;
  415.  
  416. {
  417.   Bool trim = T;
  418.   char *np = oldstring, ch;
  419.   int len;
  420.   
  421.   if (pretrim) {
  422.      while (trim && ('\0' != (ch = *np))) {
  423.        trim = (0 != index(trimchars,ch));
  424.        if (trim) np++;
  425.      }
  426.      strcpy(oldstring,np);
  427.   }
  428.   if (1 >= (len = strlen(oldstring)) && pretrim) return(len);
  429.   if (posttrim) {
  430.      np = oldstring + len - 1;
  431.      while (T) {
  432.        ch = *np;
  433.        trim = (0 != index(trimchars,ch));
  434.        if (trim) *np == '\0';
  435.        if (!trim || np == oldstring) break;
  436.        np--;
  437.      }
  438.   }
  439.   return(strlen(oldstring));
  440. }
  441.   
  442. int string_trim (newstring,oldstring,trimchars,pretrim,posttrim)
  443.  
  444.   char *newstring, *oldstring, *trimchars;
  445.   Bool pretrim, posttrim;
  446.   
  447. {  
  448.   strcpy(newstring,oldstring);
  449.   return(ip_string_trim(newstring,trimchars,pretrim,posttrim));
  450. }
  451.  
  452. char *string_upcase (astring) char *astring;
  453. {
  454.   while (*astring) {
  455.     *astring = to_upper_if_lower(*astring);
  456.     astring++;
  457.   }
  458. }
  459.  
  460. char *string_downcase (astring) char *astring;
  461. {
  462.   while (*astring) {
  463.     *astring = to_lower_if_upper(*astring);
  464.     astring++;
  465.   }
  466. }
  467.  
  468.  
  469. yes_or_no_check (astring) char *astring;
  470.  
  471. /* returns 1 if yes, 0 if no, -1 if neither */
  472. /* works for 'Y' 'YES' 'NO' 'N' in any capitalization */
  473.  
  474. {  
  475.   int len;
  476.   len = strlen(astring);
  477.   if (len == 0 || len > 3) return(-1);
  478.   if (0 == nocase_compare(astring,len,"YES",3) || 
  479.       0 == nocase_compare(astring,len,"Y",1))
  480.      return(1);
  481.   if (0 == nocase_compare(astring,len,"NO",2) || 
  482.       0 == nocase_compare(astring,len,"N",1))
  483.      return(0);
  484.   return(-1);
  485. }
  486.  
  487.  
  488. Bool all_digits (astring) char *astring;
  489.  
  490. /* test whether every character is a digit (0-9) */
  491.  
  492. {
  493.   while (*astring != '\0') 
  494.     if (!isdigit(*astring++)) return(F);
  495.   return(T);
  496. }
  497.  
  498.  
  499. Bool all_whitespace (astring) char *astring;
  500.  
  501. /* test whether every character is a blank or a tab */
  502.  
  503. {
  504.   register char ch;
  505.   while ((ch = *astring++) != '\0') {
  506.     if (ch == ' ' || ch == '\t') continue;
  507.     return(F);
  508.   }
  509.   return(T);
  510. }
  511.  
  512. Bool all_uppercase(astring) char *astring;
  513. {
  514.   register char ch;
  515.   while ((ch = *astring++) != '\0') {
  516.     if (!isupper(ch)) return(F);
  517.   }
  518.   return(T);
  519. }
  520.  
  521. Bool all_lowercase(astring) char *astring;
  522. {
  523.   register char ch;
  524.   while ((ch = *astring++) != '\0') {
  525.     if (!islower(ch)) return(F);
  526.   }
  527.   return(T);
  528. }
  529.  
  530. Bool all_alphabetic(astring) char *astring;
  531. {
  532.   register char ch;
  533.   while ((ch = *astring++) != '\0') {
  534.     if (!isalpha(ch)) return(F);
  535.   }
  536.   return(T);
  537. }
  538.  
  539. Bool all_ascii(astring) char *astring;
  540. {
  541.   register char ch;
  542.   while ((ch = *astring++) != '\0') {
  543.     if (!isascii(ch)) return(F);
  544.   }
  545.   return(T);
  546. }
  547.  
  548. Bool all_alphanumeric(astring) char *astring;
  549. {
  550.   register char ch;
  551.   while ((ch = *astring++) != '\0') {
  552.     if (!isalnum(ch)) return(F);
  553.   }
  554.   return(T);
  555. }
  556.  
  557. int str_to_pos_int (astring,low,high) char *astring; int low,high;
  558.  
  559.   /* returns -1 if *astring is not composed of digits. */
  560.   /* returns -2 if the integer is out of range. */
  561.   /* treats all digit strings as decimal. */
  562.  
  563. {
  564.   int value,len,maxlen,j;
  565.   maxlen = strlen(MAXINTSTR);
  566.   len = strlen(astring);
  567.   if (!all_digits(astring)) return(-1);
  568.   if (len > maxlen) return(-2);
  569.   if (len == maxlen) {
  570.      if (1 == strcmp(astring,MAXINTSTR)) return(-2);
  571.   }
  572.   for (j = 0; j < len-1; j++) {
  573.       if (*astring != '0') break;
  574.       astring++;
  575.   }
  576.   sscanf(astring,"%d",&value);
  577.   if (value < low || value > high) return(-2);
  578.   return(value);
  579. }
  580.  
  581.  
  582. int sreverse (buffer,astring) char *buffer, *astring;
  583. {
  584.   register int last = strlen(astring);
  585.   buffer[last--] = '\0';
  586.   while (last >= 0) buffer[last--] = *astring++;
  587. }
  588.  
  589. char * ip_sreverse (astring) char *astring;
  590. {
  591.   register int last = strlen(astring) - 1;
  592.   register int first = 0;
  593.   register char ch;
  594.   while (first < last) {
  595.     ch = astring[first];
  596.     astring[first++] = astring[last];
  597.     astring[last--] = ch;
  598.   }
  599.   return(astring);
  600. }
  601.  
  602.  
  603.  
  604. static char pathbuffer[PATH_MAXPATHLEN];
  605.  
  606.  
  607. char *temp_path (dir,filename) char *dir; char *filename;
  608.  
  609. {
  610.   return(make_path(dir,filename,"",F));
  611. }
  612.  
  613.  
  614. char *perm_path (dir,filename) char *dir; char *filename;
  615.  
  616. {
  617.   return(make_path(dir,filename,"",T));
  618. }
  619.  
  620.  
  621. char *make_path_numeric_extension (dir,filename,extension,perm)
  622.  
  623.   char *dir, *filename;
  624.   int extension;
  625.   Bool perm;
  626.  
  627. {
  628.   char buffer[20];
  629.   sprintf(buffer,"%d",extension);
  630.   return(make_path(dir,filename,buffer,perm));
  631. }
  632.  
  633.  
  634. char *make_path (dir,filename,extension,perm)
  635.  
  636.   char *dir, *filename, *extension;
  637.   Bool perm;
  638.  
  639. {
  640.   char *rval;
  641.   if (!perm && (strlen(dir) + 1 + strlen(filename) + strlen(extension) + 1 >=
  642.                 PATH_MAXPATHLEN)) {
  643.      return((char *) 0);
  644.   }
  645.   nbuffconcat(pathbuffer,4,dir,"/",filename,extension);
  646.   if (!perm) return(pathbuffer);
  647.   rval = emalloc(strlen(pathbuffer) + 1);  
  648.   strcpy(rval,pathbuffer);
  649.   return(rval);
  650. }
  651.  
  652.  
  653. char *just_filename (path,new,perm) char *path; Bool new,perm;
  654.  
  655. {
  656.   char *fnp,*rval;
  657.   fnp = (0 == (fnp = rindex(path,'/'))) ? path : fnp + 1;
  658.   if (!new) return(fnp);
  659.   if (!perm) {
  660.      strcpy(pathbuffer,fnp);
  661.      return(pathbuffer);
  662.   }
  663.   else {
  664.      rval = emalloc(strlen(fnp) + 1);
  665.      strcpy(rval,fnp);
  666.      return(rval);
  667.   }
  668. }
  669.  
  670.  
  671.  
  672. read_yes_or_no (iport,oport,prompt,helpstring,quitstring)
  673.  
  674.   /* prints prompt, then reads from port until it gets 'Y', 'N', 'YES' or */
  675.   /* 'NO' (case independently).  If helpstring and/or quitstring are not */
  676.   /* "" or (char *) 0 then if the user types in one of those ANSWER_HELP */
  677.   /* or ANSWER_QUIT are returned, otherwise ANSWER_NO or ANSWER_YES are */
  678.   /* eventually returned. */
  679.  
  680.   FILE *iport, *oport;
  681.   char *prompt, *helpstring, *quitstring;
  682.  
  683. {
  684.   char buffer[20],buffer2[20];
  685.   int bl,hl,ql,len;
  686.   
  687.   buffer[19] = '\0';
  688.   
  689.   while (T) {
  690.         
  691.     fprintf(oport,"%s",prompt);
  692.     switch (len = getline(iport,buffer,20)) {
  693.       case (AT_EOF) :
  694.         return(ANSWER_EOF);
  695.         break;
  696.       case (TOO_MANY_CHARS) :
  697.         break;
  698.       default :
  699.         if (0 == (bl = remove_excess_blanks(buffer2,buffer))) break;
  700.         switch (yes_or_no_check(buffer2)) {
  701.           case (0) :
  702.             return(ANSWER_NO);
  703.           case (1) :
  704.             return(ANSWER_YES);
  705.           case (-1) :
  706.             if (helpstring != (char *) 0 && (hl = strlen(helpstring)) > 0) {
  707.                if (0 == nocase_compare(buffer2,bl,helpstring,hl)) {
  708.                   return(ANSWER_HELP);
  709.                }
  710.             }
  711.             if (quitstring != (char *) 0 && (ql = strlen(quitstring)) > 0) {
  712.                if (0 == nocase_compare(buffer2,bl,quitstring,ql)) {
  713.                   return(ANSWER_QUIT);
  714.                }
  715.             }
  716.             break;
  717.         }   
  718.         break;
  719.     }
  720.    
  721.     fprintf(oport,"Please answer 'YES' or 'NO'\n");
  722.     continue;
  723.    
  724.   }
  725.     
  726. }
  727.  
  728.  
  729. int getline (iport,buffer,buflen) FILE *iport; char *buffer; int buflen;
  730.  
  731.   /* reads a line into buffer.  Does not put the '\n' into buffer. */
  732.   /* Returns AT_EOF if at end of file when called.  If it encounters */
  733.   /* end of file after reading at least one character, the eof is treated */
  734.   /* as if it were a newline.   Returns TOO_MANY_CHARS if more than */
  735.   /* buflen - 1 characters are read before encountering a newline. */        
  736.   /* In this case exactly buflen - 1 characters are read. */
  737.   /* The last character read is always follwed by a '\0'. */
  738.   /* if successful getline returns the number of characters read exclusive */
  739.   /* of a terminating newline or eof. */
  740.  
  741. {
  742.   int ch;
  743.   char *bptr = buffer;
  744.   int nchars = 0;
  745.   
  746.   if (buflen <= 0) return(TOO_MANY_CHARS);
  747.   
  748.   while (T) {
  749.     switch (ch = getc(iport)) {
  750.       case (EOF) :
  751.       case ('\n') :
  752.         if (ch == EOF && nchars == 0) return(AT_EOF);
  753.         *bptr = '\0';
  754.         return(nchars);
  755.       default :
  756.         if (++nchars == buflen) { 
  757.            *bptr = '\0';
  758.            ungetc(ch,iport);
  759.            return(TOO_MANY_CHARS);
  760.         }
  761.         *bptr++ = ch;
  762.     }
  763.     
  764.   }
  765.     
  766. }
  767.  
  768.  
  769. int getlines (fp,n,ptr_lines,linebuf,maxlinelen)
  770.  
  771.   /* See documentation for getfile below */
  772.  
  773.   FILE *fp;
  774.   int n;
  775.   char ***ptr_lines;
  776.   char *linebuf;
  777.   int maxlinelen;
  778.  
  779. {
  780.   int len;
  781.   char *line;
  782.   if (0 > (len = getline(fp,linebuf,maxlinelen))) {
  783.      if (len == AT_EOF) {
  784.         *ptr_lines = (char **) emalloc(n * sizeof(char **));
  785.         return(n);
  786.      }
  787.      else {
  788.         return(TOO_MANY_CHARS);
  789.      }
  790.   }
  791.   else {
  792.      line = emalloc(len+1);
  793.      strcpy(line,linebuf);
  794.      len = getlines(fp,n+1,ptr_lines,linebuf,maxlinelen);
  795.      if (len == TOO_MANY_CHARS) return(TOO_MANY_CHARS);
  796.      (*ptr_lines)[n] = line;
  797.      return(len);
  798.   }
  799. }
  800.  
  801.  
  802. int getfile (filename,ptr_lines,linebuf,maxlinelen)
  803.  
  804.   /* read in a file as an array of character strings */
  805.   /* 'maxlinelen+1' is the maximum length a line of the file is allowed */
  806.   /* to be.  'linebuf' must be at least 'maxlinelen+1' characters long. */
  807.   /* Returns the number of lines in the file (and therefore the number */
  808.   /* of entries in *ptr_lines) if successful.  Returns IOERROR if it */
  809.   /* could not open the file to read from. Returns TOO_MANY_CHARS if */
  810.   /* it encounters a line longer than 'maxlinelen' characters. */
  811.  
  812.   /* Space for each line is malloc'ed as it is read in and the text for */
  813.   /* the jth line is stored in (*ptr_lines)[j] */
  814.  
  815.   char *filename;
  816.   char ***ptr_lines;
  817.   char *linebuf;
  818.   int maxlinelen;
  819.  
  820. {
  821.   FILE *fp;
  822.   int nlines;
  823.   if (NULL == (fp = fopen(filename,"r"))) return(IOERROR);
  824.   nlines = getlines(fp,0,ptr_lines,linebuf,maxlinelen);
  825.   fclose(fp);
  826.   return(nlines);
  827. }
  828.  
  829.  
  830. int ngetlines (fp,n,ptr_lines,linebuf,maxlinelen)
  831.  
  832.   /* See documentation for ngetfile below */
  833.  
  834.   FILE *fp;
  835.   int n;
  836.   char ***ptr_lines;
  837.   char *linebuf;
  838.   int maxlinelen;
  839.  
  840. {
  841.   int len;
  842.   int nlines = 0;
  843.   *ptr_lines = (char **) emalloc(n * sizeof(char **));
  844.   while (T) {
  845.     if (0 > (len = getline(fp,linebuf,maxlinelen))) {
  846.        if (len == AT_EOF) {
  847.           return(nlines);
  848.        }
  849.        else {
  850.           return(TOO_MANY_CHARS);
  851.        }
  852.     }
  853.     else {
  854.        if (++nlines > n) {
  855.           return(TOO_MANY_LINES);
  856.        }
  857.        (*ptr_lines)[nlines-1] = anewstr(linebuf);
  858.     }
  859.   }
  860. }
  861.  
  862.  
  863.  
  864. int ngetfile (n,filename,ptr_lines,linebuf,maxlinelen)
  865.  
  866.   /* Same as getfile except that at most n lines will be read. */
  867.   /* If it attempts to read more than n lines, TOO_MANY_LINES will */
  868.   /* be returned. */
  869.  
  870.   int n;
  871.   char *filename;
  872.   char ***ptr_lines;
  873.   char *linebuf;
  874.   int maxlinelen;
  875.  
  876. {
  877.   FILE *fp;
  878.   int nlines;
  879.   if (NULL == (fp = fopen(filename,"r"))) return(IOERROR);
  880.   nlines = ngetlines(fp,n,ptr_lines,linebuf,maxlinelen);
  881.   fclose(fp);
  882.   return(nlines);
  883. }
  884.  
  885.  
  886. extern int read_file_into_buffer (
  887.  
  888.        filename,ptr_lines,maxlines,buffer,buflen,linebuffer,linebuflen
  889.  
  890.     )
  891.        
  892.   char *filename; 
  893.   char ***ptr_lines;
  894.   int maxlines;
  895.   char *buffer;
  896.   int buflen;
  897.   char *linebuffer;
  898.   int linebuflen;
  899.  
  900.   /* *ptr_lines should be an array of character string pointers maxlines */
  901.   /* big.  buffer should be an array of characters buflen long.  The routine */
  902.   /* reads lines using getline and stores them into buffer, terminating each */
  903.   /* with a null.  A pointer to the nth line read is stored in *ptr_lines[n] */
  904.   /* Returns IOERROR if it cannot open the file for reading, TOO_MANY_LINES */
  905.   /* if more than maxlines were read in, TOO_MANY_CHARS if buffer is */
  906.   /* filled before end of file is reached, and LINE_TOO_LONG is any line is */
  907.   /* longer than linebuflen.  Returns number of lines read in if successful. */
  908.   
  909. {  
  910.   FILE *fp;
  911.   int linecount,charcount,len;
  912.   char *bp;
  913.   char **lines;
  914.   
  915.   if (NULL == (fp = fopen(filename,"r"))) return(IOERROR);
  916.   linecount = 0;
  917.   charcount = 0;
  918.   bp = buffer;
  919.   lines = *ptr_lines;
  920.   
  921.   while (T) {
  922.         
  923.     if (0 > (len = getline(fp,linebuffer,linebuflen))) {
  924.        fclose(fp);
  925.        if (len == AT_EOF) {
  926.           return(linecount);
  927.        }
  928.        else {
  929.           return(LINE_TOO_LONG);
  930.        }
  931.     }
  932.     
  933.     if (linecount >= maxlines) {
  934.        fclose(fp);
  935.        return(TOO_MANY_LINES);
  936.     }
  937.     
  938.     charcount += len;
  939.     if (charcount >= buflen) {
  940.        fclose(fp);
  941.        return(TOO_MANY_CHARS);
  942.     }
  943.     
  944.     strcpy(bp,linebuffer);
  945.     lines[linecount++] = bp;
  946.     bp += (len + 1);
  947.   
  948.   }
  949.   
  950. }
  951.   
  952. extern char *efopen (filename,mode) char *filename; char *mode;
  953.  
  954.   /* The routine simply calls fopen with the same arguments, but prints a */
  955.   /* reasonable error message and calls exit if the call to fopen fails. */
  956.  
  957. {
  958.   FILE *fp;
  959.   if (NULL == (fp = fopen(filename,mode))) {
  960.      fprintf(stderr,"Could not open %s, mode: %s\n",filename,mode);
  961.      perror("Reason: ");
  962.      exit(1);
  963.   }
  964.   return((char *) fp);
  965. }
  966.  
  967.  
  968.  
  969. extern int record_fseek (fp,rnum,fromwhere,rsize,hdrsize)
  970.  
  971.   FILE *fp;
  972.   long rnum;
  973.   int fromwhere;
  974.   int rsize;
  975.   int hdrsize; 
  976.  
  977. {
  978.   if (fromwhere == 0) {
  979.      return(fseek(fp,(long) ((rnum - 1)*rsize + hdrsize),0));
  980.   }
  981.   else {
  982.      return(fseek(fp,(long) (rnum*rsize),fromwhere));
  983.   }
  984. }
  985.  
  986.  
  987. Bool check_string (s,minlen,maxlen) char *s; long minlen,maxlen;
  988. {
  989.   long len;
  990.   if (s == 0) return(F);
  991.   len = strlen(s);
  992.   return (len >= minlen && len <= maxlen);
  993. }
  994.  
  995.