home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / gnu / sh-utils-1.12-src.lha / sh-utils-1.12 / lib / getline.c < prev    next >
C/C++ Source or Header  |  1994-11-04  |  3KB  |  127 lines

  1. /* getline.c -- Replacement for GNU C library function getline
  2.  
  3. Copyright (C) 1993 Free Software Foundation, Inc.
  4.  
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the
  8. License, or (at your option) any later version.
  9.  
  10. This program is distributed in the hope that it will be useful, but
  11. WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  18.  
  19. /* Written by Jan Brittenson, bson@gnu.ai.mit.edu.  */
  20.  
  21. #ifdef HAVE_CONFIG_H
  22. #include <config.h>
  23. #endif
  24.  
  25. #include <sys/types.h>
  26. #include <stdio.h>
  27. #define NDEBUG
  28. #include <assert.h>
  29.  
  30. #if STDC_HEADERS
  31. #include <stdlib.h>
  32. #else
  33. char *malloc (), *realloc ();
  34. #endif
  35.  
  36. /* Always add at least this many bytes when extending the buffer.  */
  37. #define MIN_CHUNK 64
  38.  
  39. /* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR
  40.    + OFFSET (and null-terminate it). *LINEPTR is a pointer returned from
  41.    malloc (or NULL), pointing to *N characters of space.  It is realloc'd
  42.    as necessary.  Return the number of characters read (not including the
  43.    null terminator), or -1 on error or EOF.  */
  44.  
  45. int
  46. getstr (lineptr, n, stream, terminator, offset)
  47.      char **lineptr;
  48.      size_t *n;
  49.      FILE *stream;
  50.      char terminator;
  51.      int offset;
  52. {
  53.   int nchars_avail;        /* Allocated but unused chars in *LINEPTR.  */
  54.   char *read_pos;        /* Where we're reading into *LINEPTR. */
  55.   int ret;
  56.  
  57.   if (!lineptr || !n || !stream)
  58.     return -1;
  59.  
  60.   if (!*lineptr)
  61.     {
  62.       *n = MIN_CHUNK;
  63.       *lineptr = malloc (*n);
  64.       if (!*lineptr)
  65.     return -1;
  66.     }
  67.  
  68.   nchars_avail = *n - offset;
  69.   read_pos = *lineptr + offset;
  70.  
  71.   for (;;)
  72.     {
  73.       register int c = getc (stream);
  74.  
  75.       /* We always want at least one char left in the buffer, since we
  76.      always (unless we get an error while reading the first char)
  77.      NUL-terminate the line buffer.  */
  78.  
  79.       assert(*n - nchars_avail == read_pos - *lineptr);
  80.       if (nchars_avail < 1)
  81.     {
  82.       if (*n > MIN_CHUNK)
  83.         *n *= 2;
  84.       else
  85.         *n += MIN_CHUNK;
  86.  
  87.       nchars_avail = *n + *lineptr - read_pos;
  88.       *lineptr = realloc (*lineptr, *n);
  89.       if (!*lineptr)
  90.         return -1;
  91.       read_pos = *n - nchars_avail + *lineptr;
  92.       assert(*n - nchars_avail == read_pos - *lineptr);
  93.     }
  94.  
  95.       if (c == EOF || ferror (stream))
  96.     {
  97.       /* Return partial line, if any.  */
  98.       if (read_pos == *lineptr)
  99.         return -1;
  100.       else
  101.         break;
  102.     }
  103.  
  104.       *read_pos++ = c;
  105.       nchars_avail--;
  106.  
  107.       if (c == terminator)
  108.     /* Return the line.  */
  109.     break;
  110.     }
  111.  
  112.   /* Done - NUL terminate and return the number of chars read.  */
  113.   *read_pos = '\0';
  114.  
  115.   ret = read_pos - (*lineptr + offset);
  116.   return ret;
  117. }
  118.  
  119. int
  120. getline (lineptr, n, stream)
  121.      char **lineptr;
  122.      size_t *n;
  123.      FILE *stream;
  124. {
  125.   return getstr (lineptr, n, stream, '\n', 0);
  126. }
  127.