diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-11-09 19:15:23 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-11-09 19:22:50 +0200 |
commit | 63bb8d52fdfed913318a7990416a60d61237bec5 (patch) | |
tree | 20135c90097cd93e6a44ffc11695bd69c6d6248e /src | |
parent | 706bb744d7ca1a090fd06fb75c8f3af5732eb368 (diff) | |
download | cflow-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')
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/argcv.c | 411 | ||||
-rw-r--r-- | src/argcv.h | 54 | ||||
-rw-r--r-- | src/parser.c | 11 |
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 @@ -15,16 +15,18 @@ # # 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. -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\ gnu.c\ linked-list.c\ main.c\ @@ -34,13 +36,13 @@ cflow_SOURCES = \ posix.c\ rc.c\ symbol.c 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 CFLOW_FLAGS=-i^s --brief cflow_CFLOW_INPUT=$(cflow_OBJECTS:.@OBJEXT@=.c) diff --git a/src/argcv.c b/src/argcv.c new file mode 100644 index 0000000..51e335e --- /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], "e); + + 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 --- /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 @@ -979,15 +979,20 @@ declare(Ident *ident, int maybe_knr) sp = get_symbol(ident->name); if (sp->source) { if (ident->storage == StaticStorage && (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")); } } sp->type = SymIdentifier; |