summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfergus.henderson <fergushenderson@users.noreply.github.com>2009-07-24 16:31:07 +0000
committerfergus.henderson <fergushenderson@users.noreply.github.com>2009-07-24 16:31:07 +0000
commit8f268d30d81e54814d8036fbee59d25020682f60 (patch)
treeadc0450607f0fbf3d312fd86358952e861bcf11e
parent8ce4277885cc4a080945942672a4e00b379ab147 (diff)
downloaddistcc-git-8f268d30d81e54814d8036fbee59d25020682f60.tar.gz
Define a GNU-compatible getline() implementation,
in case we don't have getline() available. Reviewed by Craig Silverstein.
-rw-r--r--Makefile.in9
-rw-r--r--configure.ac1
-rw-r--r--src/h_getline.c64
-rw-r--r--src/util.c46
-rw-r--r--src/util.h5
-rwxr-xr-xtest/testdistcc.py37
6 files changed, 160 insertions, 2 deletions
diff --git a/Makefile.in b/Makefile.in
index 29a66f7..03cd878 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -304,6 +304,7 @@ h_compile_obj = src/h_compile.o $(common_obj) src/compile.o src/timefile.o \
src/backoff.o src/emaillog.o src/remote.o src/clinet.o \
src/clirpc.o src/include_server_if.o src/state.o src/where.o \
src/ssh.o src/strip.o src/cpp.o
+h_getline_obj = src/h_getline.o $(common_obj)
# All source files, for the purposes of building the distribution
SRC = src/stats.c \
@@ -318,7 +319,7 @@ SRC = src/stats.c \
src/h_argvtostr.c \
src/h_exten.c src/h_hosts.c src/h_issource.c src/h_parsemask.c \
src/h_sa2str.c src/h_scanargs.c src/h_strip.c \
- src/h_dotd.c src/h_compile.c \
+ src/h_dotd.c src/h_compile.c src/h_getline.c \
src/help.c src/history.c src/hosts.c src/hostfile.c \
src/implicit.c src/io.c \
src/loadfile.c src/lock.c \
@@ -422,7 +423,8 @@ check_PROGRAMS = \
h_scanargs@EXEEXT@ \
h_strip@EXEEXT@ \
h_dotd@EXEEXT@ \
- h_compile@EXEEXT@
+ h_compile@EXEEXT@ \
+ h_getline@EXEEXT@
check_include_server_PY = \
include_server/c_extensions_test.py \
@@ -536,6 +538,9 @@ h_fix_debug_info@EXEEXT@: $(h_fix_debug_info)
h_compile@EXEEXT@: $(h_compile_obj)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_compile_obj) $(LIBS)
+h_getline@EXEEXT@: $(h_getline_obj)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(h_getline_obj) $(LIBS)
+
src/h_fix_debug_info.o: src/fix_debug_info.c
$(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) \
diff --git a/configure.ac b/configure.ac
index fab20b4..44921b1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -381,6 +381,7 @@ AC_CHECK_FUNCS([getaddrinfo getnameinfo inet_ntop inet_ntoa])
AC_CHECK_FUNCS([strndup strsep mmap strlcpy])
AC_CHECK_FUNCS([getloadavg])
+AC_CHECK_FUNCS([getline])
AC_CHECK_DECLS([snprintf, vsnprintf, vasprintf, asprintf, strndup])
diff --git a/src/h_getline.c b/src/h_getline.c
new file mode 100644
index 0000000..83eb9bf
--- /dev/null
+++ b/src/h_getline.c
@@ -0,0 +1,64 @@
+/* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*-
+ * Copyright 2009 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+*/
+
+/* Author: Fergus Henderson */
+
+/*
+ * h_getline.cc:
+ * Helper for tests of getline().
+ */
+
+#include <config.h>
+#include "distcc.h"
+#include "util.h"
+#include <stdlib.h>
+
+const char *rs_program_name = "h_getline";
+
+int main(int argc, char** argv) {
+ char *line;
+ size_t n;
+ int c, i;
+
+ if (argc > 1) {
+ n = atoi(argv[1]);
+ line = malloc(n);
+ } else {
+ n = 0;
+ line = NULL;
+ }
+
+ printf("original n = %lu, ", (unsigned long) n);
+ long result = getline(&line, &n, stdin);
+ if (result > (long) n) {
+ fprintf(stderr, "ERROR: return value > buffer size\n");
+ exit(1);
+ }
+ printf("returned %ld, ", (long) result);
+ printf("n = %lu, ", (unsigned long) n);
+ printf("line = '");
+ for (i = 0; i < result; i++) {
+ putchar(line[i]);
+ }
+ printf("', rest = '");
+ while ((c = getchar()) != EOF)
+ putchar(c);
+ printf("'\n");
+ return 0;
+}
diff --git a/src/util.c b/src/util.c
index a4c446f..560797f 100644
--- a/src/util.c
+++ b/src/util.c
@@ -796,3 +796,49 @@ int dcc_tokenize_string(const char *input, char ***argv_ptr)
free(input_copy);
return 0;
}
+
+#ifndef HAVE_GETLINE
+ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
+ static const int buffer_size_increment = 100;
+ char *buffer;
+ size_t size;
+ size_t bytes_read;
+ int c;
+ char *new_buffer;
+
+ if (lineptr == NULL || stream == NULL || n == NULL ||
+ (*lineptr == NULL && *n != 0)) {
+ /* Invalid parameters. */
+ return -1;
+ }
+
+ buffer = *lineptr;
+ size = *n;
+
+ bytes_read = 0;
+ do {
+ /* Ensure that we have space for next character or '\0'. */
+ if (bytes_read + 1 > size) {
+ size += buffer_size_increment;
+ new_buffer = realloc(buffer, size);
+ if (new_buffer == NULL) {
+ /* Out of memory. */
+ *lineptr = buffer;
+ *n = size - buffer_size_increment;
+ return -1;
+ }
+ buffer = new_buffer;
+ }
+ if ((c = fgetc(stream)) == EOF)
+ break;
+ buffer[bytes_read++] = c;
+ } while (c != '\n');
+ buffer[bytes_read] = '\0';
+
+ *lineptr = buffer;
+ *n = size;
+
+ /* We return -1 on EOF for compatibility with GNU getline(). */
+ return bytes_read == 0 ? -1 : (ssize_t) bytes_read;
+}
+#endif
diff --git a/src/util.h b/src/util.h
index b20b3e2..d32b37b 100644
--- a/src/util.h
+++ b/src/util.h
@@ -22,6 +22,7 @@
*/
#include <setjmp.h>
+#include <stdio.h>
/* util.c */
int dcc_getcurrentload(void);
@@ -54,3 +55,7 @@ size_t strlcpy(char *d, const char *s, size_t bufsize);
#endif
int dcc_tokenize_string(const char *in, char ***argv_ptr);
+
+#ifndef HAVE_GETLINE
+ssize_t getline(char **lineptr, size_t *n, FILE *stream);
+#endif
diff --git a/test/testdistcc.py b/test/testdistcc.py
index 97e5316..0501c1b 100755
--- a/test/testdistcc.py
+++ b/test/testdistcc.py
@@ -2101,6 +2101,42 @@ class Lsdistcc_Case(WithDaemon_Case):
self.assert_re_search("127.0.0.4:%d\n" % self.server_port, out)
self.assert_re_search("127.0.0.5:%d\n" % self.server_port, out)
+class Getline_Case(comfychair.TestCase):
+ """Test getline()."""
+ values = [
+ # Input, Line, Rest, Retval
+ ('', '', '', -1),
+ ('\n', '\n', '', 1),
+ ('\n\n', '\n', '\n', 1),
+ ('\n\n\n', '\n', '\n\n', 1),
+ ('a', 'a', '', 1),
+ ('a\n', 'a\n', '', 2),
+ ('foo', 'foo', '', 3),
+ ('foo\n', 'foo\n', '', 4),
+ ('foo\nbar\n', 'foo\n', 'bar\n', 4),
+ ('foobar\nbaz', 'foobar\n', 'baz', 7),
+ ('foo bar\nbaz', 'foo bar\n', 'baz', 8),
+ ]
+ def runtest(self):
+ for input, line, rest, retval in Getline_Case.values:
+ for bufsize in [None, 0, 1, 2, 3, 4, 64, 10000]:
+ if bufsize:
+ cmd = "printf '%s' | h_getline %s | cat -v" % (input,
+ bufsize)
+ n = bufsize
+ else:
+ cmd = "printf '%s' | h_getline | cat -v" % input
+ n = 0
+ ret, msgs, err = self.runcmd_unchecked(cmd)
+ self.assert_equal(ret, 0);
+ self.assert_equal(err, '');
+ msg_parts = msgs.split(',');
+ self.assert_equal(msg_parts[0], "original n = %s" % n);
+ self.assert_equal(msg_parts[1], " returned %s" % retval);
+ self.assert_equal(msg_parts[2].startswith(" n = "), True);
+ self.assert_equal(msg_parts[3], " line = '%s'" % line);
+ self.assert_equal(msg_parts[4], " rest = '%s'\n" % rest);
+
# When invoking compiler, use absolute path so distccd can find it
for path in os.environ['PATH'].split (':'):
abs_path = os.path.join (path, 'gcc')
@@ -2169,6 +2205,7 @@ tests = [
EmptySource_Case,
HostFile_Case,
AbsSourceFilename_Case,
+ Getline_Case,
# slow tests below here
Concurrent_Case,
HundredFold_Case,