summaryrefslogtreecommitdiffabout
path: root/src
authorSergey Poznyakoff <gray@gnu.org.ua>2009-11-09 17:15:23 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2009-11-09 17:22:50 (GMT)
commit63bb8d52fdfed913318a7990416a60d61237bec5 (patch) (side-by-side diff)
tree20135c90097cd93e6a44ffc11695bd69c6d6248e /src
parent706bb744d7ca1a090fd06fb75c8f3af5732eb368 (diff)
downloadcflow-63bb8d52fdfed913318a7990416a60d61237bec5.tar.gz
cflow-63bb8d52fdfed913318a7990416a60d61237bec5.tar.bz2
Housekeeping changes.
* .gitmodules: Make gnulib a submodule. * Makefile.am (SUBDIRS): Rename `lib' to `gnu'. * configure.ac: Likewise. * README-hacking: Update * bootstrap, bootstrap.conf: Update. * gnulib.modules: Remove `malloc'. * lib/Makefile.am: Remove. * lib/argcv.c, lib/argcv.h: Move to src. * po/POTFILES.in, src/Makefile.am: Reflect the above changes. * src/parser.c (declare): Improve diagnostic messages.
Diffstat (limited to 'src') (more/less context) (ignore whitespace changes)
-rw-r--r--src/Makefile.am6
-rw-r--r--src/argcv.c411
-rw-r--r--src/argcv.h54
-rw-r--r--src/parser.c11
4 files changed, 477 insertions, 5 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index ce4663d..05acd30 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,10 +18,12 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA.
-INCLUDES = -I$(top_srcdir)/lib -I../ -I../lib
+INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu
bin_PROGRAMS = cflow
cflow_SOURCES = \
+ argcv.c\
+ argcv.h\
c.l\
cflow.h\
depmap.c\
@@ -37,7 +39,7 @@ cflow_SOURCES = \
localedir = $(datadir)/locale
-cflow_LDADD=../lib/libcflow.a @LIBINTL@
+LDADD=../gnu/libgnu.a @LIBINTL@
AM_CPPFLAGS=-DLOCALEDIR=\"$(localedir)\"
AM_LFLAGS=-dvp
EXTRA_DIST=cflow.rc
diff --git a/src/argcv.c b/src/argcv.c
new file mode 100644
index 0000000..51e335e
--- a/dev/null
+++ b/src/argcv.c
@@ -0,0 +1,411 @@
+/* argcv.c - simple functions for parsing input based on whitespace
+ Copyright (C) 1999, 2000, 2001, 2005, 2007 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <argcv.h>
+
+/*
+ * takes a string and splits it into several strings, breaking at ' '
+ * command is the string to split
+ * the number of strings is placed into argc
+ * the split strings are put into argv
+ * returns 0 on success, nonzero on failure
+ */
+
+#define isws(c) ((c)==' '||(c)=='\t'||(c)=='\n')
+#define isdelim(c,delim) (strchr(delim,(c))!=NULL)
+
+static int
+argcv_scan (int len, const char *command, const char *delim, const char* cmnt,
+ int *start, int *end, int *save)
+{
+ int i = 0;
+
+ for (;;)
+ {
+ i = *save;
+
+ if (i >= len)
+ return i + 1;
+
+ /* Skip initial whitespace */
+ while (i < len && isws (command[i]))
+ i++;
+ *start = i;
+
+ if (!isdelim (command[i], delim))
+ {
+ while (i < len)
+ {
+ if (command[i] == '\\')
+ {
+ if (++i == len)
+ break;
+ i++;
+ continue;
+ }
+
+ if (command[i] == '\'' || command[i] == '"')
+ {
+ int j;
+ for (j = i+1; j < len && command[j] != command[i]; j++)
+ if (command[j] == '\\')
+ j++;
+ if (j < len)
+ i = j+1;
+ else
+ i++;
+ }
+ else if (isws (command[i]) || isdelim (command[i], delim))
+ break;
+ else
+ i++; /* skip the escaped character */
+ }
+ i--;
+ }
+
+ *end = i;
+ *save = i + 1;
+
+ /* If we have a token, and it starts with a comment character, skip
+ to the newline and restart the token search. */
+ if (*save <= len)
+ {
+ if (cmnt && strchr (cmnt, command[*start]) != NULL)
+ {
+ i = *save;
+ while (i < len && command[i] != '\n')
+ i++;
+
+ *save = i;
+ continue;
+ }
+ }
+ break;
+ }
+ return *save;
+}
+
+static char quote_transtab[] = "\\\\a\ab\bf\fn\nr\rt\t";
+
+int
+argcv_unquote_char (int c)
+{
+ char *p;
+
+ for (p = quote_transtab; *p; p += 2)
+ {
+ if (*p == c)
+ return p[1];
+ }
+ return c;
+}
+
+int
+argcv_quote_char (int c)
+{
+ char *p;
+
+ for (p = quote_transtab + sizeof(quote_transtab) - 2;
+ p > quote_transtab; p -= 2)
+ {
+ if (*p == c)
+ return p[-1];
+ }
+ return -1;
+}
+
+#define to_num(c) \
+ (isdigit(c) ? c - '0' : (isxdigit(c) ? toupper(c) - 'A' + 10 : 255 ))
+
+static int
+xtonum (int *pval, const char *src, int base, int cnt)
+{
+ int i, val;
+
+ for (i = 0, val = 0; i < cnt; i++, src++)
+ {
+ int n = *(unsigned char*)src;
+ if (n > 127 || (n = to_num(n)) >= base)
+ break;
+ val = val*base + n;
+ }
+ *pval = val;
+ return i;
+}
+
+size_t
+argcv_quoted_length (const char *str, int *quote)
+{
+ size_t len = 0;
+
+ *quote = 0;
+ for (; *str; str++)
+ {
+ if (*str == ' ')
+ {
+ len++;
+ *quote = 1;
+ }
+ else if (*str == '"' || *str == '\'')
+ {
+ len += 2;
+ *quote = 1;
+ }
+ else if (*str != '\t' && *str != '\\' && isprint (*str))
+ len++;
+ else if (argcv_quote_char (*str) != -1)
+ len += 2;
+ else
+ len += 4;
+ }
+ return len;
+}
+
+void
+argcv_unquote_copy (char *dst, const char *src, size_t n)
+{
+ int i = 0;
+ int c;
+ int expect_delim = 0;
+
+ while (i < n)
+ {
+ switch (src[i])
+ {
+ case '\'':
+ case '"':
+ if (!expect_delim)
+ {
+ const char *p;
+
+ for (p = src+i+1; *p && *p != src[i]; p++)
+ if (*p == '\\')
+ p++;
+ if (*p)
+ expect_delim = src[i++];
+ else
+ *dst++ = src[i++];
+ }
+ else if (expect_delim == src[i])
+ ++i;
+ else
+ *dst++ = src[i++];
+ break;
+
+ case '\\':
+ ++i;
+ if (src[i] == 'x' || src[i] == 'X')
+ {
+ if (n - i < 2)
+ {
+ *dst++ = '\\';
+ *dst++ = src[i++];
+ }
+ else
+ {
+ int off = xtonum(&c, src + i + 1, 16, 2);
+ if (off == 0)
+ {
+ *dst++ = '\\';
+ *dst++ = src[i++];
+ }
+ else
+ {
+ *dst++ = c;
+ i += off + 1;
+ }
+ }
+ }
+ else if ((unsigned char)src[i] < 128 && isdigit(src[i]))
+ {
+ if (n - i < 1)
+ {
+ *dst++ = '\\';
+ *dst++ = src[i++];
+ }
+ else
+ {
+ int off = xtonum(&c, src+i, 8, 3);
+ if (off == 0)
+ {
+ *dst++ = '\\';
+ *dst++ = src[i++];
+ }
+ else
+ {
+ *dst++ = c;
+ i += off;
+ }
+ }
+ }
+ else
+ *dst++ = argcv_unquote_char (src[i++]);
+ break;
+
+ default:
+ *dst++ = src[i++];
+ }
+ }
+ *dst = 0;
+}
+
+void
+argcv_quote_copy (char *dst, const char *src)
+{
+ for (; *src; src++)
+ {
+ if (*src == '"' || *src == '\'')
+ {
+ *dst++ = '\\';
+ *dst++ = *src;
+ }
+ else if (*src != '\t' && *src != '\\' && isprint(*src))
+ *dst++ = *src;
+ else
+ {
+ int c = argcv_quote_char (*src);
+ *dst++ = '\\';
+ if (c != -1)
+ *dst++ = c;
+ else
+ {
+ char tmp[4];
+ snprintf (tmp, sizeof tmp, "%03o", *(unsigned char*)src);
+ memcpy (dst, tmp, 3);
+ dst += 3;
+ }
+ }
+ }
+}
+
+int
+argcv_get (const char *command, const char *delim, const char *cmnt,
+ int *argc, char ***argv)
+{
+ int len = strlen (command);
+ int i = 0;
+ int start, end, save;
+
+ *argv = NULL;
+
+ /* Count number of arguments */
+ *argc = 0;
+ save = 0;
+
+ while (argcv_scan (len, command, delim, cmnt, &start, &end, &save) <= len)
+ (*argc)++;
+
+ *argv = calloc ((*argc + 1), sizeof (char *));
+ if (*argv == NULL)
+ return ENOMEM;
+
+ i = 0;
+ save = 0;
+ for (i = 0; i < *argc; i++)
+ {
+ int n;
+ argcv_scan (len, command, delim, cmnt, &start, &end, &save);
+
+ if ((command[start] == '"' || command[end] == '\'')
+ && command[end] == command[start])
+ {
+ start++;
+ end--;
+ }
+ n = end - start + 1;
+ (*argv)[i] = calloc (n+1, sizeof (char));
+ if ((*argv)[i] == NULL)
+ return ENOMEM;
+ argcv_unquote_copy ((*argv)[i], &command[start], n);
+ (*argv)[i][n] = 0;
+ }
+ (*argv)[i] = NULL;
+ return 0;
+}
+
+/*
+ * frees all elements of an argv array
+ * argc is the number of elements
+ * argv is the array
+ */
+int
+argcv_free (int argc, char **argv)
+{
+ while (--argc >= 0)
+ if (argv[argc])
+ free (argv[argc]);
+ free (argv);
+ return 0;
+}
+
+/* Take a argv an make string separated by ' '. */
+
+int
+argcv_string (int argc, char **argv, char **pstring)
+{
+ size_t i, j, len;
+ char *buffer;
+
+ /* No need. */
+ if (pstring == NULL)
+ return EINVAL;
+
+ buffer = malloc (1);
+ if (buffer == NULL)
+ return ENOMEM;
+ *buffer = '\0';
+
+ for (len = i = j = 0; i < argc; i++)
+ {
+ int quote;
+ int toklen;
+
+ toklen = argcv_quoted_length (argv[i], &quote);
+
+ len += toklen + 2;
+ if (quote)
+ len += 2;
+
+ buffer = realloc (buffer, len);
+ if (buffer == NULL)
+ return ENOMEM;
+
+ if (i != 0)
+ buffer[j++] = ' ';
+ if (quote)
+ buffer[j++] = '"';
+ argcv_quote_copy (buffer + j, argv[i]);
+ j += toklen;
+ if (quote)
+ buffer[j++] = '"';
+ }
+
+ for (; j > 0 && isspace (buffer[j-1]); j--)
+ ;
+ buffer[j] = 0;
+ if (pstring)
+ *pstring = buffer;
+ return 0;
+}
+
diff --git a/src/argcv.h b/src/argcv.h
new file mode 100644
index 0000000..17a2f31
--- a/dev/null
+++ b/src/argcv.h
@@ -0,0 +1,54 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999, 2000, 2001, 2005, 2007 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA */
+
+#ifndef _ARGCV_H
+#define _ARGCV_H 1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __P
+# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
+# define __P(args) args
+# else
+# define __P(args) ()
+# endif
+#endif /*__P */
+
+extern int argcv_get __P ((const char *command, const char *delim,
+ const char* cmnt,
+ int *argc, char ***argv));
+extern int argcv_string __P ((int argc, char **argv, char **string));
+extern int argcv_free __P ((int argc, char **argv));
+extern int argcv_unquote_char __P((int c));
+extern int argcv_quote_char __P((int c));
+extern size_t argcv_quoted_length __P((const char *str, int *quote));
+extern void argcv_unquote_copy __P((char *dst, const char *src, size_t n));
+extern void argcv_quote_copy __P((char *dst, const char *src));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ARGCV_H */
diff --git a/src/parser.c b/src/parser.c
index 16ab289..6478ed5 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -982,9 +982,14 @@ declare(Ident *ident, int maybe_knr)
&& (sp->storage != StaticStorage || level > 0)) {
sp = install_ident(ident->name, ident->storage);
} else {
- error_at_line(0, 0, filename, ident->line,
- _("%s/%d redefined"),
- ident->name, sp->arity);
+ if (sp->arity >= 0)
+ error_at_line(0, 0, filename, ident->line,
+ _("%s/%d redefined"),
+ ident->name, sp->arity);
+ else
+ error_at_line(0, 0, filename, ident->line,
+ _("%s redefined"),
+ ident->name);
error_at_line(0, 0, sp->source, sp->def_line,
_("this is the place of previous definition"));
}

Return to:

Send suggestions and report system problems to the System administrator.