diff options
author | fergus.henderson <fergus.henderson@01de4be4-8c4a-0410-9132-4925637da917> | 2009-07-24 16:31:07 +0000 |
---|---|---|
committer | fergus.henderson <fergus.henderson@01de4be4-8c4a-0410-9132-4925637da917> | 2009-07-24 16:31:07 +0000 |
commit | f6114da67e23955a9ff34ac8f76e9ba0a4b890ae (patch) | |
tree | adc0450607f0fbf3d312fd86358952e861bcf11e | |
parent | 4a1a1b13bd23bb4a1ce3e28cd554a3d92858bdb4 (diff) | |
download | distcc-f6114da67e23955a9ff34ac8f76e9ba0a4b890ae.tar.gz |
Define a GNU-compatible getline() implementation,
in case we don't have getline() available.
Reviewed by Craig Silverstein.
git-svn-id: http://distcc.googlecode.com/svn/trunk@701 01de4be4-8c4a-0410-9132-4925637da917
-rw-r--r-- | Makefile.in | 9 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/h_getline.c | 64 | ||||
-rw-r--r-- | src/util.c | 46 | ||||
-rw-r--r-- | src/util.h | 5 | ||||
-rwxr-xr-x | test/testdistcc.py | 37 |
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; +} @@ -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 @@ -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, |