/* Copyright (C) 1993 Hongjiu Lu This file is part of the Linux C Library. The Linux C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Linux C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. */ #ifdef __linux__ #include #include #include #if !defined(ssize_t) && !defined(_SSIZE_T) #define _SSIZE_T #define ssize_t __ssize_t #endif #endif #include #include #include #ifndef MAX_CANON #define MAX_CANON 256 #endif /* Read up to (and including) a newline from STREAM into * *LINEPTR (and null-terminate it). *LINEPTR is a pointer * returned from malloc (or NULL), pointing to *N characters * of space. It is realloc'd as necessary. Returns the * number of characters read (not including the null * terminator), or -1 on error or EOF. */ #ifdef __linux__ ssize_t DEFUN(__getline, (lineptr, n, stream), char **lineptr AND size_t *n AND FILE *stream) #else __getline (char **lineptr, int *n, FILE *stream) #endif { char *ptr; /* the latest section of the buffer */ char *line; /* Pointer to the buffer */ int size; /* Size of the buffer */ int count; /* # of chars in the buffer */ if (lineptr == NULL || n == NULL) { errno = EINVAL; return -1; } if (ferror (stream)) return -1; /* No buffer or too small, we allocate one. */ if (*lineptr == NULL || *n < 2) { line = (*lineptr == NULL) ? malloc (MAX_CANON) : realloc (*lineptr, MAX_CANON); if (line == NULL) return -1; *lineptr = line; *n = MAX_CANON; } else { /* Assume the buffer size is `*n'. */ line = *lineptr; } size = *n; count = 0; ptr = line; for (;;) { /* We call fgets () first. For the first time, our * buffer is *n. Next time, it is MAX_CANON chars * longer. Count in 1 char for the last '\0'. Our * additional buffer is MAX_CANON + 1 char long. */ if (fgets (ptr, (count > 0 ? MAX_CANON + 1: size), stream) == NULL) { /* Check if we read in anything. */ return (count) ? count : -1; } /* How many chars we have read in so far. */ count += strlen (ptr); /* If the buffer is full and we still haven't seen the * newline, we need to expand the buffer and call * fgets () again. Caution: there may be no newline * at EOF. We will catch it when we call fgets () next * time. */ if ((count >= size - 1) && line [count - 1] != '\n') { /* Expand the buffer by MAX_CANON chars. */ size += MAX_CANON; line = realloc (line, size); if (line == NULL) return -1; *lineptr = line; *n = size; /* ptr points to the newly expanded buffer. We * start at the previous '\0'. */ ptr = &line [count]; } else break; } return count; } #if 0 void main () { char *buffer = NULL; int len, ret; while ((ret = __getline (&buffer, &len, stdin)) != -1) printf ("size: %d, len: %d: %s", len, ret, buffer); } #endif