pcb 4.1.1
An interactive printed circuit board layout editor.
|
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 */