v13i052: Screen-oriented rolodex program, Part04/04

Rich Salz rsalz at bbn.com
Sat Feb 20 08:30:55 AEST 1988


Submitted-by: Dave Ihnat <ihnp4!homebru!ignatz>
Posting-number: Volume 13, Issue 52
Archive-name: rolodex/part04

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 4)."
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f './toolsdir/ctools.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./toolsdir/ctools.c'\"
else
echo shar: Extracting \"'./toolsdir/ctools.c'\" \(21027 characters\)
sed "s/^X//" >'./toolsdir/ctools.c' <<'END_OF_FILE'
X/* -*- Mode: C; Package: (CTOOLS C) -*- */
X
X#include <ctype.h>
X#include <stdio.h>
X
X#ifdef BSD42
X#include <strings.h>
X#endif
X
X#include "sys5.h"
X
X#include "ctools.h"
X
X#include "basics.h"
Xchar maxintstr[30] = { '\0' };
X
X#ifdef MSDOS
X#define rindex strrchr 
X#define index strchr
X#include <string.h>
X#endif
X
X/* miscellaneous fairly primitive routines that deal with characters, */
X/* strings, memory, simple input and pathnames. */
X 
X
X/* Author:  JP Massar */
X/* Thinking Machines Corporation */
X
X/* Included routines:
X
X   emalloc
X   anewstr
X   
X   copy
X   fill
X   
X   to_upper_if_lower
X   to_lower_if_upper
X   
X   buffconcat
X   nbuffconcat
X   
X   slcompare
X   slge_compare
X   nocase_compare
X   
X   strfind
X   strncfind
X   strsearch
X   strncsearch
X   
X   yes_or_no_check
X   
X   remove_excess_blanks
X   ip_string_trim
X   string_trim
X   string_upcase
X   string_downcase
X   
X   all_digits
X   all_whitespace
X   all_uppercase
X   all_lowercase
X   all_alphabetic
X   all_alphanumeric
X   all_ascii
X   
X   str_to_pos_int
X   
X   sreverse
X   ip_sreverse
X        
X   temp_path
X   perm_path
X   make_path_numeric_extension
X   make_path
X   just_filename
X   
X   read_yes_or_no
X   getline
X   getlines
X   ngetlines
X   getfile
X   ngetfile
X   read_file_into_buffer
X   efopen
X
X   check_int
X   check_string
X   
X*/
X   
X
Xextern char *malloc();
X
X
Xchar *emalloc (space) int space;
X
X/* allocate 'space' bytes, die if we have run out of memory. */
X
X{
X  char *rval;        
X  if (space < 0) {
X     fprintf(stderr,"Fatal error: argument to emalloc < 0\n");
X     exit(-1);
X  }
X  if (0 == (rval = malloc((unsigned) space))) {
X     fprintf(stderr,"Fatal error:  No more memory\n");
X     exit(-1);
X  }
X  return(rval);
X}  
X
X
Xchar *anewstr (astring) char *astring;
X
X/* allocate space for and then copy a string.  Returns pointer to */
X/* new string. */
X
X{        
X  char *newstr;
X  newstr = emalloc(strlen(astring)+1);
X  strcpy(newstr,astring);
X  return(newstr);
X}
X
X
Xcopy (dest,src,n)
X
X  /* copy n bytes */
X
X  register char *dest,*src;
X  register int n;
X
X  { register int j = 0;
X    while (j++ < n) *dest++ = *src++; 
X  }
X 
X
Xfill (addr,ch,n)
X
X  /* fill n sequential bytes with 'ch' */
X
X  register char *addr;
X  register char ch;
X  register int n;
X  
X  { register int j = 0;
X    while (j++ < n) *addr++ = ch;
X  }
X
X
Xto_upper_if_lower (ch)
X
X  char ch;
X
X  { return(islower(ch) ? toupper(ch) : ch); }
X
X
Xto_lower_if_upper (ch)
X
X  char ch;
X
X  { return(isupper(ch) ? tolower(ch) : ch); }
X
X
Xbuffconcat (buffer,s1,s2) 
X
X  /* concatenate two null terminated strings into a buffer. */
X
X  char *buffer, *s1, *s2;
X  
X  { while (*s1 != '\0') *buffer++ = *s1++;
X    while (*s2 != '\0') *buffer++ = *s2++;
X    *buffer = '\0';
X  }
X
X
Xnbuffconcat (buffer,n,s1,s2,s3,s4,s5,s6)
X
X  /* concatenates up to 6 strings into a buffer.  Returns -1 if n */
X  /* is not reasonable, otherwise returns 0. */
X
X  char *buffer;
X  int n;
X  char *s1,*s2,*s3,*s4,*s5,*s6;
X
X{
X  register char *b;
X  register char *s;
X  int i;
X  b = buffer;
X  if (n < 1 || n > 6) return(-1);
X  for (i = 1; i <= 6; i++) {
X      if (i > n) break;
X      switch (i) {
X        case 1 : s = s1; break;
X        case 2 : s = s2; break;
X        case 3 : s = s3; break;
X        case 4 : s = s4; break;
X        case 5 : s = s5; break;
X        case 6 : s = s6; break;
X      }
X      while (*s != '\0') *b++ = *s++;
X  }
X  *b = '\0';
X  return(0);
X}
X
X
Xslcompare (s1,l1,s2,l2)
X
X  /* compare strings with possible nulls in them given their lengths */
X  /* only returns EQUAL (0) or NOT EQUAL (-1) */
X
X  char *s1;
X  int l1;
X  char *s2;
X  int l2;
X
X  { int j;
X    if (l1 != l2) return(-1);
X    j = 0;
X    while (j++ < l1) 
X      if (*s1++ != *s2++) return(-1);
X    return(0);
X  }
X
X  
Xslge_compare (s1,l1,s2,l2)
X
X  /* returns -1 if s1 < s2; 1 if s2 < s1; 0 if s1 = s2 */
X  /* ignores nulls in the strings */
X
X  char *s1;
X  int l1;
X  char *s2;
X  int l2;
X
X  { int j,len;
X    j = 0;
X    len = l2 > l1 ? l1 : l2;
X    while (j++ < len) {
X      if (*s1 != *s2) 
X         return((*s1 < *s2) ? -1 : 1);
X      s1++;   
X      s2++;
X    }  
X    return((l2 == l1) ? 0 : ((l1 < l2) ? -1 : 1));
X  }
X
Xnocase_compare (s1,l1,s2,l2)
X
X  /* treats nulls as normal characters.  Returns same as slge_compare */
X
X  char *s1;
X  int l1;
X  char *s2;
X  int l2;
X
X  { int j,len,ch1,ch2;
X    j = 0;
X    len = l2 > l1 ? l1 : l2;
X    while (j++ < len) {
X      ch1 = to_upper_if_lower(*s1++);
X      ch2 = to_upper_if_lower(*s2++);
X      if (ch1 != ch2) {
X         return((ch1 < ch2) ? -1 : 1);
X      }
X    }  
X    return((l2 == l1) ? 0 : ((l1 < l2) ? -1 : 1));
X  }
X
X
Xchar *strfind(s1,s2,fast)  
X  
X  register char *s1;
X  char *s2;
X  Bool fast;
X  
X{  
X  register int len1,len2;
X  len2 = strlen(s2);
X  if (fast) {
X     while (*s1 != '\0')
X       if (0 == strncmp(s1++,s2,len2)) return(s1-1);
X  }  
X  else {
X     len1 = strlen(s1);
X     while (len1 >= len2) {
X       if (0 == strncmp(s1++,s2,len2)) return(s1-1);
X       len1--;
X     }
X  }
X  return(0);
X}     
X
X
Xchar *strncfind(s1,s2,fast)
X
X  register char *s1;
X  char *s2;
X  Bool fast;
X  
X{  
X  register int len1,len2;
X  len2 = strlen(s2);
X  if (fast) {
X     while (*s1 != '\0')
X       if (0 == nocase_compare(s1++,len2,s2,len2)) return(s1-1);
X  }
X  else {
X     len1 = strlen(s1);
X     while (len1 >= len2) {
X       if (0 == nocase_compare(s1++,len2,s2,len2)) return(s1-1);
X       len1--;
X     }
X  }
X  return(0);
X}  
X
X  
Xchar *strsearch(s1,s1len,s2,s2len)
X
X  /* do a substring search without noticing nulls */
X  /* finds s2 in s1, returns pointer into s1 or 0 */
X
X  register char *s1, *s2;
X  register int s1len,s2len;
X  
X  {  register char *pc;
X     register char *bound;
X     register char *pctemp;
X     register char *s2temp;
X     register int j;
X
X     bound = s1 + s1len - s2len;
X     for (pc = s1; pc <= bound; pc++) {
X         pctemp = pc;
X         s2temp = s2;
X         for (j = 0; j < s2len; j++)
X             if (*pctemp++ != *s2temp++) goto not_here;
X         return(pc);       
X         not_here :
X         continue;
X     }    
X     return(0);
X}
X
X
Xchar *strncsearch(s1,s1len,s2,s2len)
X
X  /* do a substring search without noticing nulls */
X  /* finds s2 in s1, returns pointer into s1 or 0 */
X  /* case independent */
X
X  register char *s1, *s2;
X  register int s1len,s2len;
X  
X  {  register char *pc;
X     register char *bound;
X     register char *pctemp;
X     register char *s2temp;
X     register int j;
X     char ch1, ch2;
X
X     bound = s1 + s1len - s2len;
X     for (pc = s1; pc <= bound; pc++) {
X         pctemp = pc;
X         s2temp = s2;
X         for (j = 0; j < s2len; j++) {
X             ch1 = *pctemp++;
X             ch2 = *s2temp++;
X             if (to_upper_if_lower(ch1) != to_upper_if_lower(ch2))
X                goto not_here;
X         }
X         return(pc);       
X         not_here :
X         continue;
X     }    
X     return(0);
X}
X
X
Xint remove_excess_blanks (newstring,oldstring) 
X
X  /* it is assumed that newstring is as long as oldstring if necessary */
X
X  char *newstring,*oldstring;
X
X{
X  int count = 0;
X  int space_found = 0;
X
X  /* skip over all blanks at beginning */
X  
X  if (*oldstring == ' ') {
X     while (*oldstring == ' ') oldstring++;
X  }
X
X  while (*oldstring != '\0') {
X        if (space_found && *oldstring == ' ') {
X           oldstring++;
X           continue;
X        }
X        space_found = (*oldstring == ' ');
X        *newstring++ = *oldstring++;
X        count++;
X  }
X
X  *newstring = '\0';
X  if (count > 0 && *(newstring - 1) == ' ') {
X     count--;
X     *(newstring - 1) = '\0';
X  }
X
X  return(count);
X
X}
X
Xint ip_string_trim (oldstring,trimchars,pretrim,posttrim)
X
X  char *oldstring, *trimchars;
X  Bool pretrim,posttrim;
X
X{
X  Bool trim = T;
X  char *np = oldstring, ch;
X  int len;
X  
X  if (pretrim) {
X     while (trim && ('\0' != (ch = *np))) {
X       trim = (0 != index(trimchars,ch));
X       if (trim) np++;
X     }
X     strcpy(oldstring,np);
X  }
X  if (1 >= (len = strlen(oldstring)) && pretrim) return(len);
X  if (posttrim) {
X     np = oldstring + len - 1;
X     while (T) {
X       ch = *np;
X       trim = (0 != index(trimchars,ch));
X       if (trim) *np = '\0';
X       if (!trim || np == oldstring) break;
X       np--;
X     }
X  }
X  return(strlen(oldstring));
X}
X  
Xint string_trim (newstring,oldstring,trimchars,pretrim,posttrim)
X
X  char *newstring, *oldstring, *trimchars;
X  Bool pretrim, posttrim;
X  
X{  
X  strcpy(newstring,oldstring);
X  return(ip_string_trim(newstring,trimchars,pretrim,posttrim));
X}
X
Xstring_upcase (astring) char *astring;
X{
X  while (*astring) {
X    *astring = to_upper_if_lower(*astring);
X    astring++;
X  }
X}
X
Xstring_downcase (astring) char *astring;
X{
X  while (*astring) {
X    *astring = to_lower_if_upper(*astring);
X    astring++;
X  }
X}
X
X
Xyes_or_no_check (astring) char *astring;
X
X/* returns 1 if yes, 0 if no, -1 if neither */
X/* works for 'Y' 'YES' 'NO' 'N' in any capitalization */
X
X{  
X  int len;
X  len = strlen(astring);
X  if (len == 0 || len > 3) return(-1);
X  if (0 == nocase_compare(astring,len,"YES",3) || 
X      0 == nocase_compare(astring,len,"Y",1))
X     return(1);
X  if (0 == nocase_compare(astring,len,"NO",2) || 
X      0 == nocase_compare(astring,len,"N",1))
X     return(0);
X  return(-1);
X}
X
X
XBool all_digits (astring) char *astring;
X
X/* test whether every character is a digit (0-9) */
X
X{
X  while (*astring != '\0') 
X    if (!isdigit(*astring++)) return(F);
X  return(T);
X}
X
X
XBool all_whitespace (astring) char *astring;
X
X/* test whether every character is a blank or a tab */
X
X{
X  register char ch;
X  while ((ch = *astring++) != '\0') {
X    if (ch == ' ' || ch == '\t') continue;
X    return(F);
X  }
X  return(T);
X}
X
XBool all_uppercase(astring) char *astring;
X{
X  register char ch;
X  while ((ch = *astring++) != '\0') {
X    if (!isupper(ch)) return(F);
X  }
X  return(T);
X}
X
XBool all_lowercase(astring) char *astring;
X{
X  register char ch;
X  while ((ch = *astring++) != '\0') {
X    if (!islower(ch)) return(F);
X  }
X  return(T);
X}
X
XBool all_alphabetic(astring) char *astring;
X{
X  register char ch;
X  while ((ch = *astring++) != '\0') {
X    if (!isalpha(ch)) return(F);
X  }
X  return(T);
X}
X
XBool all_ascii(astring) char *astring;
X{
X  register char ch;
X  while ((ch = *astring++) != '\0') {
X    if (!isascii(ch)) return(F);
X  }
X  return(T);
X}
X
XBool all_alphanumeric(astring) char *astring;
X{
X  register char ch;
X  while ((ch = *astring++) != '\0') {
X    if (!isalnum(ch)) return(F);
X  }
X  return(T);
X}
X
Xint str_to_pos_int (astring,low,high) char *astring; int low,high;
X
X  /* returns -1 if *astring is not composed of digits. */
X  /* returns -2 if the integer is out of range. */
X  /* treats all digit strings as decimal. */
X
X{
X  int value,len,maxlen,j;
X  maxlen = strlen(MAXINTSTR);
X  len = strlen(astring);
X  if (!all_digits(astring)) return(-1);
X  if (len > maxlen) return(-2);
X  if (len == maxlen) {
X     if (1 == strcmp(astring,MAXINTSTR)) return(-2);
X  }
X  for (j = 0; j < len-1; j++) {
X      if (*astring != '0') break;
X      astring++;
X  }
X  sscanf(astring,"%d",&value);
X  if (value < low || value > high) return(-2);
X  return(value);
X}
X
X
Xint sreverse (buffer,astring) char *buffer, *astring;
X{
X  register int last = strlen(astring);
X  buffer[last--] = '\0';
X  while (last >= 0) buffer[last--] = *astring++;
X}
X
Xchar * ip_sreverse (astring) char *astring;
X{
X  register int last = strlen(astring) - 1;
X  register int first = 0;
X  register char ch;
X  while (first < last) {
X    ch = astring[first];
X    astring[first++] = astring[last];
X    astring[last--] = ch;
X  }
X  return(astring);
X}
X
X
X
Xstatic char pathbuffer[PATH_MAXPATHLEN];
X
X
Xchar *temp_path (dir,filename) char *dir; char *filename;
X
X{
X  return(make_path(dir,filename,"",F));
X}
X
X
Xchar *perm_path (dir,filename) char *dir; char *filename;
X
X{
X  return(make_path(dir,filename,"",T));
X}
X
X
Xchar *make_path_numeric_extension (dir,filename,extension,perm)
X
X  char *dir, *filename;
X  int extension;
X  Bool perm;
X
X{
X#ifdef UNIX
X  char *sprintf();
X#else
X  int sprintf();
X#endif
X  char buffer[20];
X  sprintf(buffer,"%d",extension);
X  return(make_path(dir,filename,buffer,perm));
X}
X
X
Xchar *make_path (dir,filename,extension,perm)
X
X  char *dir, *filename, *extension;
X  Bool perm;
X
X{
X  char *rval;
X  if (!perm && (strlen(dir) + 1 + strlen(filename) + strlen(extension) + 1 >=
X                PATH_MAXPATHLEN)) {
X     return((char *) 0);
X  }
X#ifdef UNIX
X  nbuffconcat(pathbuffer,4,dir,"/",filename,extension);
X#endif
X
X#ifdef VMS
X  nbuffconcat(pathbuffer,4,dir,filename,extension);
X#endif
X
X#ifdef MSDOS
X  nbuffconcat(pathbuffer,4,dir,"/",filename,extension);
X#endif
X
X  if (!perm) return(pathbuffer);
X  rval = emalloc(strlen(pathbuffer) + 1);  
X  strcpy(rval,pathbuffer);
X  return(rval);
X}
X
X
Xchar *just_filename (path,new,perm) char *path; Bool new,perm;
X
X{
X  char *fnp,*rval;
X#ifdef UNIX
X  fnp = ((char *)NULL == (fnp = rindex(path,'/'))) ? path : fnp + 1;
X#endif
X
X#ifdef VMS
X  fnp = ((char *)NULL == (fnp = rindex(path,']'))) ? path : fnp + 1;
X#endif
X
X#ifdef MSDOS
X  if((fnp = rindex(path,'/')) != (char *)NULL)
X	fnp += 1;
X
X  if(fnp == (char *)NULL)
X	if((fnp = rindex(path,'\\')) == (char *)NULL)
X		fnp = path;
X	else
X		fnp += 1;
X#endif
X
X  if (!new) return(fnp);
X  if (!perm) {
X     strcpy(pathbuffer,fnp);
X     return(pathbuffer);
X  }
X  else {
X     rval = emalloc(strlen(fnp) + 1);
X     strcpy(rval,fnp);
X     return(rval);
X  }
X}
X
X
X
Xread_yes_or_no (iport,oport,prompt,helpstring,quitstring)
X
X  /* prints prompt, then reads from port until it gets 'Y', 'N', 'YES' or */
X  /* 'NO' (case independently).  If helpstring and/or quitstring are not */
X  /* "" or (char *) 0 then if the user types in one of those ANSWER_HELP */
X  /* or ANSWER_QUIT are returned, otherwise ANSWER_NO or ANSWER_YES are */
X  /* eventually returned. */
X
X  FILE *iport, *oport;
X  char *prompt, *helpstring, *quitstring;
X
X{
X  char buffer[20],buffer2[20];
X  int bl,hl,ql;
X  
X  buffer[19] = '\0';
X  
X  while (T) {
X        
X    fprintf(oport,"%s",prompt);
X    switch ((char)getline(iport,buffer,20)) {
X      case (AT_EOF) :
X        return(ANSWER_EOF);
X        /* break; */
X      case (TOO_MANY_CHARS) :
X        break;
X      default :
X        if (0 == (bl = remove_excess_blanks(buffer2,buffer))) break;
X        switch (yes_or_no_check(buffer2)) {
X          case (0) :
X            return(ANSWER_NO);
X          case (1) :
X            return(ANSWER_YES);
X          case (-1) :
X            if (helpstring != (char *) 0 && (hl = strlen(helpstring)) > 0) {
X               if (0 == nocase_compare(buffer2,bl,helpstring,hl)) {
X                  return(ANSWER_HELP);
X               }
X            }
X            if (quitstring != (char *) 0 && (ql = strlen(quitstring)) > 0) {
X               if (0 == nocase_compare(buffer2,bl,quitstring,ql)) {
X                  return(ANSWER_QUIT);
X               }
X            }
X            break;
X        }   
X        break;
X    }
X   
X    fprintf(oport,"Please answer 'YES' or 'NO'\n");
X    continue;
X   
X  }
X    
X}
X
X
Xint getline (iport,buffer,buflen) FILE *iport; char *buffer; int buflen;
X
X  /* reads a line into buffer.  Does not put the '\n' into buffer. */
X  /* Returns AT_EOF if at end of file when called.  If it encounters */
X  /* end of file after reading at least one character, the eof is treated */
X  /* as if it were a newline.   Returns TOO_MANY_CHARS if more than */
X  /* buflen - 1 characters are read before encountering a newline. */        
X  /* In this case exactly buflen - 1 characters are read. */
X  /* The last character read is always follwed by a '\0'. */
X  /* if successful getline returns the number of characters read exclusive */
X  /* of a terminating newline or eof. */
X
X{
X  int ch;
X  char *bptr = buffer;
X  int nchars = 0;
X  
X  if (buflen <= 0) return(TOO_MANY_CHARS);
X  
X  while (T) {
X    switch (ch = getc(iport)) {
X      case (EOF) :
X      case ('\n') :
X        if (ch == EOF && nchars == 0) return(AT_EOF);
X        *bptr = '\0';
X        return(nchars);
X      default :
X        if (++nchars == buflen) { 
X           *bptr = '\0';
X           ungetc(ch,iport);
X           return(TOO_MANY_CHARS);
X        }
X        *bptr++ = ch;
X    }
X    
X  }
X    
X}
X
X
Xint getlines (fp,n,ptr_lines,linebuf,maxlinelen)
X
X  /* See documentation for getfile below */
X
X  FILE *fp;
X  int n;
X  char ***ptr_lines;
X  char *linebuf;
X  int maxlinelen;
X
X{
X  int len;
X  char *line;
X  if (0 > (len = getline(fp,linebuf,maxlinelen))) {
X     if (len == AT_EOF) {
X        *ptr_lines = (char **) emalloc(n * sizeof(char **));
X        return(n);
X     }
X     else {
X        return(TOO_MANY_CHARS);
X     }
X  }
X  else {
X     line = emalloc(len+1);
X     strcpy(line,linebuf);
X     len = getlines(fp,n+1,ptr_lines,linebuf,maxlinelen);
X     if (len == TOO_MANY_CHARS) return(TOO_MANY_CHARS);
X     (*ptr_lines)[n] = line;
X     return(len);
X  }
X}
X
X
Xint getfile (filename,ptr_lines,linebuf,maxlinelen)
X
X  /* read in a file as an array of character strings */
X  /* 'maxlinelen+1' is the maximum length a line of the file is allowed */
X  /* to be.  'linebuf' must be at least 'maxlinelen+1' characters long. */
X  /* Returns the number of lines in the file (and therefore the number */
X  /* of entries in *ptr_lines) if successful.  Returns IOERROR if it */
X  /* could not open the file to read from. Returns TOO_MANY_CHARS if */
X  /* it encounters a line longer than 'maxlinelen' characters. */
X
X  /* Space for each line is malloc'ed as it is read in and the text for */
X  /* the jth line is stored in (*ptr_lines)[j] */
X
X  char *filename;
X  char ***ptr_lines;
X  char *linebuf;
X  int maxlinelen;
X
X{
X  FILE *fp;
X  int nlines;
X  if (NULL == (fp = fopen(filename,"r"))) return(IOERROR);
X  nlines = getlines(fp,0,ptr_lines,linebuf,maxlinelen);
X  fclose(fp);
X  return(nlines);
X}
X
X
Xint ngetlines (fp,n,ptr_lines,linebuf,maxlinelen)
X
X  /* See documentation for ngetfile below */
X
X  FILE *fp;
X  int n;
X  char ***ptr_lines;
X  char *linebuf;
X  int maxlinelen;
X
X{
X  int len;
X  int nlines = 0;
X  *ptr_lines = (char **) emalloc(n * sizeof(char **));
X  while (T) {
X    if (0 > (len = getline(fp,linebuf,maxlinelen))) {
X       if (len == AT_EOF) {
X          return(nlines);
X       }
X       else {
X          return(TOO_MANY_CHARS);
X       }
X    }
X    else {
X       if (++nlines > n) {
X          return(TOO_MANY_LINES);
X       }
X       (*ptr_lines)[nlines-1] = anewstr(linebuf);
X    }
X  }
X}
X
X
X
Xint ngetfile (n,filename,ptr_lines,linebuf,maxlinelen)
X
X  /* Same as getfile except that at most n lines will be read. */
X  /* If it attempts to read more than n lines, TOO_MANY_LINES will */
X  /* be returned. */
X
X  int n;
X  char *filename;
X  char ***ptr_lines;
X  char *linebuf;
X  int maxlinelen;
X
X{
X  FILE *fp;
X  int nlines;
X  if (NULL == (fp = fopen(filename,"r"))) return(IOERROR);
X  nlines = ngetlines(fp,n,ptr_lines,linebuf,maxlinelen);
X  fclose(fp);
X  return(nlines);
X}
X
X
Xint read_file_into_buffer (
X
X       filename,ptr_lines,maxlines,buffer,buflen,linebuffer,linebuflen
X
X    )
X       
X  char *filename; 
X  char ***ptr_lines;
X  int maxlines;
X  char *buffer;
X  int buflen;
X  char *linebuffer;
X  int linebuflen;
X
X  /* *ptr_lines should be an array of character string pointers maxlines */
X  /* big.  buffer should be an array of characters buflen long.  The routine */
X  /* reads lines using getline and stores them into buffer, terminating each */
X  /* with a null.  A pointer to the nth line read is stored in *ptr_lines[n] */
X  /* Returns IOERROR if it cannot open the file for reading, TOO_MANY_LINES */
X  /* if more than maxlines were read in, TOO_MANY_CHARS if buffer is */
X  /* filled before end of file is reached, and LINE_TOO_LONG is any line is */
X  /* longer than linebuflen.  Returns number of lines read in if successful. */
X  
X{  
X  FILE *fp;
X  int linecount,charcount,len;
X  char *bp;
X  char **lines;
X  
X  if (NULL == (fp = fopen(filename,"r"))) return(IOERROR);
X  linecount = 0;
X  charcount = 0;
X  bp = buffer;
X  lines = *ptr_lines;
X  
X  while (T) {
X        
X    if (0 > (len = getline(fp,linebuffer,linebuflen))) {
X       fclose(fp);
X       if (len == AT_EOF) {
X          return(linecount);
X       }
X       else {
X          return(LINE_TOO_LONG);
X       }
X    }
X    
X    if (linecount >= maxlines) {
X       fclose(fp);
X       return(TOO_MANY_LINES);
X    }
X    
X    charcount += len;
X    if (charcount >= buflen) {
X       fclose(fp);
X       return(TOO_MANY_CHARS);
X    }
X    
X    strcpy(bp,linebuffer);
X    lines[linecount++] = bp;
X    bp += (len + 1);
X  
X  }
X  
X}
X  
Xchar *efopen (filename,mode) char *filename; char *mode;
X
X  /* The routine simply calls fopen with the same arguments, but prints a */
X  /* reasonable error message and calls exit if the call to fopen fails. */
X
X{
X  FILE *fp;
X  if (NULL == (fp = fopen(filename,mode))) {
X     fprintf(stderr,"Could not open %s, mode: %s\n",filename,mode);
X     perror("Reason: ");
X     exit(1);
X  }
X  return((char *) fp);
X}
X
X
X
Xint record_fseek (fp,rnum,fromwhere,rsize,hdrsize)
X
X  FILE *fp;
X  long rnum;
X  int fromwhere;
X  int rsize;
X  int hdrsize; 
X
X{
X  if (fromwhere == 0) {
X     return(fseek(fp,(long) ((rnum - 1)*rsize + hdrsize),0));
X  }
X  else {
X     return(fseek(fp,(long) (rnum*rsize),fromwhere));
X  }
X}
X
X
XBool check_string (s,minlen,maxlen) char *s; long minlen,maxlen;
X{
X  long len;
X  if (s == 0) return(F);
X  len = strlen(s);
X  return (len >= minlen && len <= maxlen);
X}
END_OF_FILE
if test 21027 -ne `wc -c <'./toolsdir/ctools.c'`; then
    echo shar: \"'./toolsdir/ctools.c'\" unpacked with wrong size!
fi
# end of './toolsdir/ctools.c'
fi
echo shar: End of archive 4 \(of 4\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
For comp.sources.unix stuff, mail to sources at uunet.uu.net.



More information about the Comp.sources.unix mailing list