speechd-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Add a portable implementation of getline to src/common.


From: Christopher Brannon
Subject: [PATCH] Add a portable implementation of getline to src/common.
Date: Wed, 29 Sep 2010 04:24:25 -0500

This patch adds our own implementation of getline, named spd_getline.
The function uses GLib's allocation routines.
We now use it in the server and modules.

This function was taken from OpenTTS and subsequently modified.
---
 include/Makefile.am        |    2 +-
 include/spd_utils.h        |   30 ++++++++++
 src/common/Makefile.am     |    5 +-
 src/common/spd_getline.c   |  132 ++++++++++++++++++++++++++++++++++++++++++++
 src/modules/dummy.c        |    5 --
 src/modules/module_main.c  |   10 +--
 src/modules/module_utils.c |   57 ++-----------------
 src/server/module.c        |    9 +--
 src/server/output.c        |   47 +---------------
 9 files changed, 179 insertions(+), 118 deletions(-)
 create mode 100644 include/spd_utils.h
 create mode 100644 src/common/spd_getline.c

diff --git a/include/Makefile.am b/include/Makefile.am
index 7767fb2..4597166 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,4 +1,4 @@
 ## Process this file with automake to produce Makefile.in
 
-noinst_HEADERS = fdsetconv.h speechd_types.h
+noinst_HEADERS = fdsetconv.h speechd_types.h spd_utils.h
 
diff --git a/include/spd_utils.h b/include/spd_utils.h
new file mode 100644
index 0000000..f07d13a
--- /dev/null
+++ b/include/spd_utils.h
@@ -0,0 +1,30 @@
+/*
+ * spd_utils.h - prototypes for utility functions used
+ * in the Speech Dispatcher server and modules.
+ *
+ * Copyright (C) 2010 Brailcom, o.p.s.
+ *
+ * This 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, or (at your option)
+ * any later version.
+ *
+ * This software 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 package; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef SPD_UTILS_H
+#define SPD_UTILS_H
+#include <stdio.h>
+#include <stddef.h>
+#include <sys/types.h>
+
+ssize_t spd_getline(char **lineptr, size_t * n, FILE * f);
+#endif /* SPD_UTILS_H */
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index f80f9b4..68c5766 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -2,5 +2,6 @@
 
 noinst_LTLIBRARIES = libcommon.la
 libcommon_la_CFLAGS = $(ERROR_CFLAGS)
-libcommon_la_CPPFLAGS = "-I$(top_srcdir)/include/"
-libcommon_la_SOURCES = fdsetconv.c
+libcommon_la_CPPFLAGS = "-I$(top_srcdir)/include/" $(GLIB_CFLAGS)
+libcommon_la_LIBADD = $(GLIB_LIBS)
+libcommon_la_SOURCES = fdsetconv.c spd_getline.c
diff --git a/src/common/spd_getline.c b/src/common/spd_getline.c
new file mode 100644
index 0000000..d81591f
--- /dev/null
+++ b/src/common/spd_getline.c
@@ -0,0 +1,132 @@
+/*
+ * spd_getline.c - portable implementation of getline
+ *
+ * Copyright (C) 2010 Brailcom, o.p.s.
+ *
+ * This 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, or (at your option)
+ * any later version.
+ *
+ * This software 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 package; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <glib.h>
+#include <spd_utils.h>
+
+#define INITIAL_BUF_SIZE 120
+#define GETLINE_FAILURE -1
+
+/*
+     * A portable implementation of getline.
+     * Originally provided by Willie Walker, and modified by Chris Brannon.
+ *
+ * Note: `*lineptr' must be a valid argument that could be passed to the
+ * `g_free()'  glib function, i.e. it must be g_malloc'ed, not malloc'ed.
+ * In all other respects, this function behaves just like the POSIX version
+ * of getline.
+ */
+
+ssize_t
+spd_getline (char **lineptr, size_t * n, FILE * f)
+{
+  char ch;
+  ssize_t buf_pos = 0;
+  ssize_t needed = 2;          /* Always buf_pos + 2 (see below). */
+  size_t new_length = 0;
+  char *temp;
+
+  if ((n == NULL) || (lineptr == NULL) || (f == NULL))
+    {
+      errno = EINVAL;
+      return GETLINE_FAILURE;
+    }
+
+  if (errno != 0)
+    errno = 0;
+
+  if ((*lineptr == NULL) || (*n == 0))
+    {
+      *n = INITIAL_BUF_SIZE;
+      *lineptr = g_malloc (*n * sizeof (char));
+
+      if (*lineptr == NULL)
+       {
+         *n = 0;
+         return GETLINE_FAILURE;       /* Out of memory. */
+       }
+    }
+
+  /*
+   * For each iteration of this loop, the following holds.
+   * We have read buf_pos bytes of the line.  The buffer contains buf_pos
+   * bytes, not including the trailing null byte at the end of the string.
+   * When we read another character, we want to store it, and we also need
+   * enough room for a null byte.  So we need to realloc as soon as our
+   * capacity becomes less than buf_pos + 2.
+   * Hence the variable "needed" which always equals buf_pos + 2.
+   */
+
+  while ((ch = getc (f)) != EOF)
+    {
+      if (errno != 0)
+       return GETLINE_FAILURE;
+
+      if (needed > *n)
+       {
+         new_length = *n * 2;
+         if (new_length <= *n)
+           {                   /* Overflow. */
+             errno = ENOMEM;
+             /* We couldn't store the character, */
+             /* so put it back on the stream. */
+             ungetc (ch, f);
+             return GETLINE_FAILURE;
+           }
+         temp = (char *) g_realloc (*lineptr, new_length * sizeof (char));
+         if (temp == NULL)
+           {
+             ungetc (ch, f);
+             return GETLINE_FAILURE;
+           }
+         *n = new_length;
+         *lineptr = temp;
+       }
+      (*lineptr)[buf_pos++] = ch;
+
+      if (ch == '\n')
+       break;
+
+      if (needed == SSIZE_MAX)
+       {
+         /* We'll overflow ssize_t on the next round. */
+         errno = ENOMEM;
+         return GETLINE_FAILURE;
+       }
+      needed++;
+    }
+  (*lineptr)[buf_pos] = '\0';
+
+  if (buf_pos == 0)
+    {
+      buf_pos = GETLINE_FAILURE;
+    }
+  return buf_pos;
+}
diff --git a/src/modules/dummy.c b/src/modules/dummy.c
index 58bb565..c9948ac 100644
--- a/src/modules/dummy.c
+++ b/src/modules/dummy.c
@@ -40,11 +40,6 @@
 
 //#define Debug 0
 
-#if !(defined(__GLIBC__) && defined(_GNU_SOURCE))
-/* Added by Willie Walker - getline is a gcc-ism */
-ssize_t getline (char **lineptr, size_t *n, FILE *f);
-#endif
-
 /* Thread and process control */
 static int dummy_speaking = 0;
 
diff --git a/src/modules/module_main.c b/src/modules/module_main.c
index 82a3220..30c3f38 100644
--- a/src/modules/module_main.c
+++ b/src/modules/module_main.c
@@ -32,13 +32,9 @@
 #include <glib.h>
 #include <dotconf.h>
 
+#include <spd_utils.h>
 #include "module_utils.h"
 
-#if !(defined(__GLIBC__) && defined(_GNU_SOURCE))
-/* Added by Willie Walker - getline is a gcc-ism */
-ssize_t getline (char **lineptr, size_t *n, FILE *f);
-#endif
-
 #define PROCESS_CMD(command, function) \
 if (!strcmp(cmd_buf, #command"\n")){ \
  char *msg; \
@@ -122,7 +118,7 @@ main(int argc, char *argv[])
     ret_init = module_init(&status_info);
 
     cmd_buf = NULL;  n=0;
-    ret = getline(&cmd_buf, &n, stdin);
+    ret = spd_getline(&cmd_buf, &n, stdin);
     if (ret == -1){
        DBG("Broken pipe when reading INIT, exiting... \n");
        module_close(2); 
@@ -152,7 +148,7 @@ main(int argc, char *argv[])
 
     while(1){
         cmd_buf = NULL;  n=0;
-        ret = getline(&cmd_buf, &n, stdin);
+        ret = spd_getline(&cmd_buf, &n, stdin);
         if (ret == -1){
             DBG("Broken pipe, exiting... \n");
             module_close(2); 
diff --git a/src/modules/module_utils.c b/src/modules/module_utils.c
index 11cbaa2..76b308c 100644
--- a/src/modules/module_utils.c
+++ b/src/modules/module_utils.c
@@ -26,60 +26,13 @@
 #endif
 
 #include <fdsetconv.h>
+#include <spd_utils.h>
 #include "module_utils.h"
 
 static char* module_audio_pars[10];
 
 extern char* module_index_mark;
 
-#if !(defined(__GLIBC__) && defined(_GNU_SOURCE))
-/* Added by Willie Walker - getline is a gcc-ism */
-#define BUFFER_LEN 256
-ssize_t getline (char **lineptr, size_t *n, FILE *f)
-{
-        char ch;
-        size_t m = 0;
-        ssize_t buf_len = 0;
-        char * buf = NULL;
-        char * p = NULL;
-
-       if (errno != 0) {
-                DBG("getline: errno came in as %d!!!\n", errno);
-               errno = 0;
-       }
-        while ( (ch = getc(f)) !=EOF )
-        {
-                if (errno != 0)
-                        return -1;
-                if ( m++ >= buf_len )
-                {
-                        buf_len += BUFFER_LEN;
-                        buf = (char *) g_realloc(buf, buf_len + 1);
-                        if ( buf == NULL )
-                        {
-                                DBG("buf==NULL");
-                                return -1;
-                        }
-                        p = buf + buf_len - BUFFER_LEN;
-                }
-                *p = ch;
-                p++;
-                if ( ch == '\n' )
-                        break;
-        }
-        if ( m == 0 )
-        {
-                DBG("getline: m=%d!",m);
-                return -1;
-        } else {
-                *p = '\0';
-                *lineptr = buf;
-                *n = m;
-                return m;
-        }
-}
-#endif /* !(defined(__GLIBC__) && defined(_GNU_SOURCE)) */
-
 char*
 do_message(EMessageType msgtype)
 {
@@ -97,7 +50,7 @@ do_message(EMessageType msgtype)
     while(1){
         cur_line = NULL;
         n = 0;
-        ret = getline(&cur_line, &n, stdin);
+        ret = spd_getline(&cur_line, &n, stdin);
         nlines++;
         if (ret == -1) return g_strdup("401 ERROR INTERNAL");
 
@@ -222,7 +175,7 @@ do_set(void)
 
     while(1){
         line = NULL; n = 0;
-        ret = getline(&line, &n, stdin);
+        ret = spd_getline(&line, &n, stdin);
         if (ret == -1){ err=1; break; }
         if (!strcmp(line, ".\n")){
             g_free(line);
@@ -279,7 +232,7 @@ do_audio(void)
 
     while(1){
         line = NULL; n = 0;
-        ret = getline(&line, &n, stdin);
+        ret = spd_getline(&line, &n, stdin);
         if (ret == -1){ err=1; break; }
         if (!strcmp(line, ".\n")){
             g_free(line);
@@ -341,7 +294,7 @@ do_loglevel(void)
 
     while(1){
         line = NULL; n = 0;
-        ret = getline(&line, &n, stdin);
+        ret = spd_getline(&line, &n, stdin);
         if (ret == -1){ err=1; break; }
         if (!strcmp(line, ".\n")){
             g_free(line);
diff --git a/src/server/module.c b/src/server/module.c
index 187d575..d0d4d06 100644
--- a/src/server/module.c
+++ b/src/server/module.c
@@ -30,14 +30,9 @@
 #include <sys/stat.h>
 #include <stdio.h>
 #include "speechd.h"
+#include <spd_utils.h>
 #include "output.h"
 
-#if !(defined(__GLIBC__) && defined(_GNU_SOURCE))
-/* Added by Willie Walker - TEMP_FAILURE_RETRY, strndup, and getline
- * are gcc-isms
- */
-ssize_t getline (char **lineptr, size_t *n, FILE *f);
-#endif
 
 void
 destroy_module(OutputModule *module)
@@ -181,7 +176,7 @@ load_output_module(char* mod_name, char* mod_prog, char* 
mod_cfgfile, char* mod_
            reply = g_string_new("\n---------------\n");
            f = fdopen(dup(module->pipe_out[0]), "r");
            while(1){
-               ret = getline(&rep_line, &n, f);
+               ret = spd_getline(&rep_line, &n, f);
                if (ret <= 0){
                    MSG(1, "ERROR: Bad syntax from output module %s 1", 
module->name);
                    return NULL;
diff --git a/src/server/output.c b/src/server/output.c
index 7f00f58..3802f83 100644
--- a/src/server/output.c
+++ b/src/server/output.c
@@ -26,6 +26,7 @@
 #endif
 
 #include <fdsetconv.h>
+#include <spd_utils.h>
 #include "output.h"
 #include "parse.h"
 
@@ -47,7 +48,7 @@ safe_write(int fd, const void *buf, size_t count) {
 #endif /* TEMP_FAILURE_RETRY */
 
 #if !(defined(__GLIBC__) && defined(_GNU_SOURCE))
-/* Added by Willie Walker - strndup, and getline are gcc-isms
+/* Added by Willie Walker - strndup is a gcc-ism
  */
 char *strndup ( const char *s, size_t n)
 {
@@ -67,48 +68,6 @@ char *strndup ( const char *s, size_t n)
 
         return p;
 }
-
-#define BUFFER_LEN 256
-ssize_t getline (char **lineptr, size_t *n, FILE *f)
-{
-        char ch;
-        size_t m = 0;
-        ssize_t buf_len = 0;
-        char * buf = NULL;
-        char * p = NULL;
-
-       if (errno != 0) {
-               errno = 0;
-       }
-        while ( (ch = getc(f)) !=EOF )
-        {
-                if (errno != 0)
-                        return -1;
-                if ( m++ >= buf_len )
-                {
-                        buf_len += BUFFER_LEN;
-                        buf = (char *) g_realloc(buf, buf_len + 1);
-                        if ( buf == NULL )
-                        {
-                                return -1;
-                        }
-                        p = buf + buf_len - BUFFER_LEN;
-                }
-                *p = ch;
-                p++;
-                if ( ch == '\n' )
-                        break;
-        }
-        if ( m == 0 )
-        {
-                return -1;
-        } else {
-                *p = '\0';
-                *lineptr = buf;
-                *n = m;
-                return m;
-        }
-}
 #endif /* !(defined(__GLIBC__) && defined(_GNU_SOURCE)) */
 
 void
@@ -227,7 +186,7 @@ output_read_reply(OutputModule *output)
     /* Wait for activity on the socket, when there is some,
        read all the message line by line */
     do{
-       bytes = getline(&line, &N, output->stream_out); 
+       bytes = spd_getline(&line, &N, output->stream_out);
        if (bytes == -1){
            MSG(2, "Error: Broken pipe to module.");
            output->working = 0;
-- 
1.7.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]