pcb 4.1.1
An interactive printed circuit board layout editor.

getline.c

Go to the documentation of this file.
00001 /* getline.c -- Replacement for GNU C library function getline
00002 
00003 Copyright (C) 1993 Free Software Foundation, Inc.
00004 
00005 This program is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU General Public License as
00007 published by the Free Software Foundation; either version 2 of the
00008 License, or (at your option) any later version.
00009 
00010 This program is distributed in the hope that it will be useful, but
00011 WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 General Public License for more details.  */
00014 
00015 /* Written by Jan Brittenson, bson@gnu.ai.mit.edu.  */
00016 
00017 #ifdef HAVE_CONFIG_H
00018 #include <config.h>
00019 #endif
00020 
00021 #if ! HAVE_GETLINE
00022 
00023 #include <sys/types.h>
00024 #include <stdio.h>
00025 #include <assert.h>
00026 #include <errno.h>
00027 
00028 #if STDC_HEADERS
00029 #include <stdlib.h>
00030 #else
00031 char *malloc (), *realloc ();
00032 #endif
00033 
00034 /* Always add at least this many bytes when extending the buffer.  */
00035 #define MIN_CHUNK 64
00036 
00037 /* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR
00038    + OFFSET (and null-terminate it). *LINEPTR is a pointer returned from
00039    malloc (or NULL), pointing to *N characters of space.  It is realloc'd
00040    as necessary.  Return the number of characters read (not including the
00041    null terminator), or -1 on error or EOF.  On a -1 return, the caller
00042    should check feof(), if not then errno has been set to indicate
00043    the error.  */
00044 
00045 int
00046 getstr (lineptr, n, stream, terminator, offset)
00047      char **lineptr;
00048      size_t *n;
00049      FILE *stream;
00050      char terminator;
00051      int offset;
00052 {
00053   int nchars_avail;             /* Allocated but unused chars in *LINEPTR.  */
00054   char *read_pos;               /* Where we're reading into *LINEPTR. */
00055   int ret;
00056 
00057   if (!lineptr || !n || !stream)
00058     {
00059       errno = EINVAL;
00060       return -1;
00061     }
00062 
00063   if (!*lineptr)
00064     {
00065       *n = MIN_CHUNK;
00066       *lineptr = malloc (*n);
00067       if (!*lineptr)
00068         {
00069           errno = ENOMEM;
00070           return -1;
00071         }
00072     }
00073 
00074   nchars_avail = *n - offset;
00075   read_pos = *lineptr + offset;
00076 
00077   for (;;)
00078     {
00079       int save_errno;
00080       register int c = getc (stream);
00081 
00082       save_errno = errno;
00083 
00084       /* We always want at least one char left in the buffer, since we
00085          always (unless we get an error while reading the first char)
00086          NUL-terminate the line buffer.  */
00087 
00088       assert((*lineptr + *n) == (read_pos + nchars_avail));
00089       if (nchars_avail < 2)
00090         {
00091           if (*n > MIN_CHUNK)
00092             *n *= 2;
00093           else
00094             *n += MIN_CHUNK;
00095 
00096           nchars_avail = *n + *lineptr - read_pos;
00097           *lineptr = realloc (*lineptr, *n);
00098           if (!*lineptr)
00099             {
00100               errno = ENOMEM;
00101               return -1;
00102             }
00103           read_pos = *n - nchars_avail + *lineptr;
00104           assert((*lineptr + *n) == (read_pos + nchars_avail));
00105         }
00106 
00107       if (ferror (stream))
00108         {
00109           /* Might like to return partial line, but there is no
00110              place for us to store errno.  And we don't want to just
00111              lose errno.  */
00112           errno = save_errno;
00113           return -1;
00114         }
00115 
00116       if (c == EOF)
00117         {
00118           /* Return partial line, if any.  */
00119           if (read_pos == *lineptr)
00120             return -1;
00121           else
00122             break;
00123         }
00124 
00125       *read_pos++ = c;
00126       nchars_avail--;
00127 
00128       if (c == terminator)
00129         /* Return the line.  */
00130         break;
00131     }
00132 
00133   /* Done - NUL terminate and return the number of chars read.  */
00134   *read_pos = '\0';
00135 
00136   ret = read_pos - (*lineptr + offset);
00137   return ret;
00138 }
00139 
00140 int
00141 getline (lineptr, n, stream)
00142      char **lineptr;
00143      size_t *n;
00144      FILE *stream;
00145 {
00146   return getstr (lineptr, n, stream, '\n', 0);
00147 }
00148 
00149 #endif /* !HAVE_GETLINE */