home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / d / libc / libc-4.6 / libc-4 / libc-linux / misc / __getline.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-23  |  3.3 KB  |  136 lines

  1. /* Copyright (C) 1993  Hongjiu Lu
  2. This file is part of the Linux C Library.
  3.  
  4. The Linux C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The Linux C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details. */
  13.  
  14. #ifdef __linux__
  15. #include <ansidecl.h>
  16. #include <stdlib.h>
  17. #include <gnu/types.h>
  18.  
  19. #if !defined(ssize_t) && !defined(_SSIZE_T)
  20. #define _SSIZE_T
  21. #define ssize_t __ssize_t
  22. #endif
  23.   
  24. #endif
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <errno.h>
  28.  
  29. #ifndef MAX_CANON
  30. #define MAX_CANON    256
  31. #endif
  32.  
  33. /* Read up to (and including) a newline from STREAM into
  34.  * *LINEPTR (and null-terminate it). *LINEPTR is a pointer
  35.  * returned from malloc (or NULL), pointing to *N characters
  36.  * of space.  It is realloc'd as necessary.  Returns the
  37.  * number of characters read (not including the null
  38.  * terminator), or -1 on error or EOF.
  39.  */
  40. #ifdef __linux__
  41. ssize_t
  42. DEFUN(__getline, (lineptr, n, stream),
  43.       char **lineptr AND size_t *n AND FILE *stream)
  44. #else       
  45. __getline (char **lineptr, int *n, FILE *stream)
  46. #endif
  47. {
  48.   char *ptr;    /* the latest section of the buffer */
  49.   char *line;    /* Pointer to the buffer */
  50.   int size;    /* Size of the buffer */
  51.   int count;    /* # of chars in the buffer */
  52.  
  53.   if (lineptr == NULL || n == NULL)
  54.   {
  55.     errno = EINVAL;
  56.     return -1;
  57.   }
  58.  
  59.   if (ferror (stream))
  60.     return -1;
  61.  
  62.   /* No buffer or too small, we allocate one. */
  63.   if (*lineptr == NULL || *n < 2)
  64.   {
  65.     line = (*lineptr == NULL) ?
  66.     malloc (MAX_CANON) : realloc (*lineptr, MAX_CANON);
  67.     if (line == NULL) return -1;
  68.     *lineptr = line;
  69.     *n = MAX_CANON;
  70.   }
  71.   else
  72.   {
  73.     /* Assume the buffer size is `*n'. */
  74.     line = *lineptr;
  75.   }
  76.  
  77.   size = *n;
  78.   count = 0;
  79.   ptr = line;
  80.  
  81.   for (;;)
  82.   {
  83.  
  84.     /* We call fgets () first. For the first time, our
  85.      * buffer is *n. Next time, it is MAX_CANON chars
  86.      * longer. Count in 1 char for the last '\0'. Our
  87.      * additional buffer is MAX_CANON + 1 char long.
  88.      */
  89.     if (fgets (ptr, (count > 0 ? MAX_CANON + 1: size), stream)
  90.     == NULL)
  91.     {
  92.       /* Check if we read in anything. */
  93.       return (count) ? count : -1;
  94.     }
  95.  
  96.     /* How many chars we have read in so far. */
  97.     count += strlen (ptr);
  98.  
  99.     /* If the buffer is full and we still haven't seen the
  100.      * newline, we need to expand the buffer and call
  101.      * fgets () again. Caution: there may be no newline
  102.      * at EOF. We will catch it when we call fgets () next
  103.      * time.
  104.      */
  105.     if ((count >= size - 1) && line [count - 1] != '\n')
  106.     {
  107.       /* Expand the buffer by MAX_CANON chars. */
  108.       size += MAX_CANON;
  109.       line = realloc (line, size); 
  110.       if (line == NULL) return -1;
  111.       *lineptr = line;
  112.       *n = size;
  113.  
  114.       /* ptr points to the newly expanded buffer. We
  115.        * start at the previous '\0'.
  116.        */
  117.       ptr = &line [count];
  118.     }
  119.     else break;
  120.   }
  121.  
  122.   return count;
  123. }
  124.  
  125. #if 0
  126. void
  127. main ()
  128. {
  129.   char *buffer = NULL;
  130.   int len, ret;
  131.  
  132.   while ((ret = __getline (&buffer, &len, stdin)) != -1)
  133.     printf ("size: %d, len: %d: %s", len, ret, buffer);
  134. }
  135. #endif
  136.