safe-strto.c: Add safe_strtoc() for parsing complex arguments
authorW. Trevor King <wking@tremily.us>
Wed, 23 Jan 2013 20:14:17 +0000 (15:14 -0500)
committerW. Trevor King <wking@tremily.us>
Mon, 11 Feb 2013 16:39:09 +0000 (11:39 -0500)
Because people may wish to use safe-strto on systems that don't
support the more recent complex.h (from C99) or may wish to avoid
linking to libm, I've masked code related to safe_strtoc() behind
HAVE_COMPLEX.  If you define this symbol, you get safe_strtoc(), but
have to link against libm.  If you don't define this symbol, you don't
get safe_strtoc().

To turn on the symbol for this project, I've created config.h.
Usually such a config header would be created via the GNU Autotools
suite (e.g. `./configure`).

config.h [new file with mode: 0644]
safe-strto.c
safe-strto.h

diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..6501584
--- /dev/null
+++ b/config.h
@@ -0,0 +1,25 @@
+/*
+Safe string-to-* conversion
+
+Copyright (C) 2013  W. Trevor King
+
+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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+
+#define HAVE_COMPLEX  /* enable safe_strtoc() */
+
+#endif  /* _CONFIG_H_ */
index 6a63dbefa72731848c7795ea5d8a059ac4506d67..e104bb58bd33d3413f60af0f071ec36fc97522aa 100644 (file)
@@ -17,10 +17,15 @@ You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include <stdlib.h>       /* for strtod(), exit(), EXIT_* */
+#include <stdlib.h>       /* for strtod(), exit(), EXIT_*, free() */
 #include <stdio.h>        /* for stderr, *printf(), perror() */
 #include <errno.h>        /* for errno */
-#include "safe-strto.h"  /* check safe_strto*() declarations */
+#include "config.h"       /* enabling safe_strtoc() */
+#ifdef HAVE_COMPLEX
+# include <string.h>       /* for strdup(), strtok_r() */
+# include <complex.h>      /* for the complex type qualifier */
+#endif  /* HAVE_COMPLEX */
+#include "safe-strto.h"   /* check safe_strto*() declarations */
 
 long int safe_strtol(const char *str, int base, const char *name)
 {
@@ -59,3 +64,33 @@ double safe_strtod(const char *str, const char *name)
        }
        return x;
 }
+
+#ifdef HAVE_COMPLEX
+
+double complex safe_strtoc(const char *str, const char *name)
+{
+       char *real, *imag, *tail, *saveptr;
+       char *local_str;
+       double complex z;
+
+       local_str = strdup(str);
+       if (!local_str) {
+               fprintf(stderr, "could not duplicate %s for %s\n", str, name);
+               perror("strdup");
+               exit(EXIT_FAILURE);
+       }
+       real = strtok_r(local_str, ",", &saveptr);
+       imag = strtok_r(NULL, ",", &saveptr);
+       tail = strtok_r(NULL, ",", &saveptr);
+       if (!real || !imag || tail) {  /* '', 'x', or 'x,y,z...' */
+               fprintf(stderr, "invalid value for %s (%s), use 'REAL,IMAGE'\n",
+                       str, name);
+               free(local_str);
+               exit(EXIT_FAILURE);
+       }
+       z = safe_strtod(real, name) + I * safe_strtod(imag, name);
+       free(local_str);
+       return z;
+}
+
+#endif  /* HAVE_COMPLEX */
index e1638433837c98d6e601d6a86df47593d66c93c5..e11219d0e31e5fcb47750a114138fe9f054b20d3 100644 (file)
@@ -23,4 +23,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 long int safe_strtol(const char *str, int base, const char *name);
 double safe_strtod(const char *str, const char *name);
 
+#ifdef HAVE_COMPLEX
+double complex safe_strtoc(const char *str, const char *name);
+#endif  /* HAVE_COMPLEX */
+
 #endif  /* _SAFE_STRTO_H_ */