diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-05 14:09:48 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-05-05 14:39:29 +0300 |
commit | 6c3f6c1b02dd5f9ac343c713bdae4aa83bafc328 (patch) | |
tree | 49bc8df1cff7157c711c63447c3e272ebc67cd4c | |
parent | a60eb4b18345626a84e23784d77ca231812e1dff (diff) | |
download | grecs-6c3f6c1b02dd5f9ac343c713bdae4aa83bafc328.tar.gz grecs-6c3f6c1b02dd5f9ac343c713bdae4aa83bafc328.tar.bz2 |
Improve node formatting. Add version comparasion functions.
* am/grecs.m4 (GRECS_SETUP): New option: shared.
* doc/GRECS_SETUP.3: Document new options.
* doc/grecs_format_locus.3: Update.
* doc/grecs_format_node.3: Document new flags.
* src/.gitignore: Update.
* src/version.c: New file.
* src/Make.am (GRECS_SRC): Add version.c
(EXTRA_DIST): Update.
* src/diag.c (default_print_diag): Flush stdout as per the docs.
* src/format.c (grecs_format_locus): Don't print trailing semicolon.
(grecs_format_value): Handle GRECS_NODE_FLAG_NOQUOTE flag.
(grecs_format_node): Print delimiters when needed.
* src/grecs.h (grecs_version_info): New struct.
(grecs_version, grecs_version_cmp): New protos.
(GRECS_NODE_FLAG_NOQUOTE): New flag.
* tests/gcfver.c: New file.
* tests/vercmp.at: New file.
* tests/.gitignore: Update.
* tests/Makefile.am: Define GRECS_VERCMP_AT in package.m4
(TESTSUITE_AT): Add vercmp.at (conditionally).
(noinst_PROGRAMS): Add gcfver.
* tests/testsuite.at: Conditionally include vercmp.at.
-rw-r--r-- | am/grecs.m4 | 20 | ||||
-rw-r--r-- | doc/GRECS_SETUP.3 | 7 | ||||
-rw-r--r-- | doc/grecs_format_locus.3 | 2 | ||||
-rw-r--r-- | doc/grecs_format_node.3 | 8 | ||||
-rw-r--r-- | src/.gitignore | 3 | ||||
-rw-r--r-- | src/Make-shared.am | 18 | ||||
-rw-r--r-- | src/Make-static.am (renamed from src/Make-noinst.am) | 0 | ||||
-rw-r--r-- | src/Make.am | 3 | ||||
-rw-r--r-- | src/diag.c | 1 | ||||
-rw-r--r-- | src/format.c | 18 | ||||
-rw-r--r-- | src/grecs.h | 15 | ||||
-rw-r--r-- | src/version.c | 86 | ||||
-rw-r--r-- | tests/.gitignore | 1 | ||||
-rw-r--r-- | tests/Makefile.am | 7 | ||||
-rw-r--r-- | tests/gcfver.c | 47 | ||||
-rw-r--r-- | tests/testsuite.at | 3 | ||||
-rw-r--r-- | tests/vercmp.at | 63 |
17 files changed, 284 insertions, 18 deletions
diff --git a/am/grecs.m4 b/am/grecs.m4 index 764ce46..e8d6915 100644 --- a/am/grecs.m4 +++ b/am/grecs.m4 @@ -147,20 +147,32 @@ AC_DEFUN([GRECS_SETUP],[ GRECS_BUILD_AUX="build-aux/getopt.m4" ]) _GRECS_IF_OPTION_SET([git2chg],[GRECS_BUILD_AUX="$GRECS_BUILD_AUX build-aux/git2chg.awk"]) + + # Make sure package versioning is compatible with vercmp.at: + s=`echo $PACKAGE_VERSION | sed 's/[0-9][0-9]*\.[0-9][0-9]*\(\.[0-9][0-9]\)\?\([^a-zA-Z_0-9].*\)\?//'` + if test -z "$s"; then + GRECS_VERCMP_AT=vercmp.at + fi + + AC_SUBST([GRECS_VERCMP_AT]) AC_SUBST([GRECS_BUILD_AUX]) AC_SUBST([GRECS_INCLUDES]) AC_SUBST([GRECS_TESTDIR]) AC_SUBST([GRECS_LDADD]) AC_SUBST([GRECS_DOCDIR]) - _GRECS_IF_OPTION_SET([install],[ + _GRECS_OPTION_SWITCH([install],[ LT_INIT GRECS_LDADD='$(top_builddir)/m4_if([$1],,grecs,$1)/src/libgrecs.la' GRECS_DOCDIR='doc' AC_CONFIG_FILES(m4_if([$1],,grecs,$1)/src/Makefile:m4_if([$1],,grecs,$1)/src/Make-inst.in m4_if([$1],,grecs,$1)/doc/Makefile) - ],[ + ],[shared],[ + LT_INIT + GRECS_LDADD='$(top_builddir)/m4_if([$1],,grecs,$1)/src/libgrecs.la' + AC_CONFIG_FILES(m4_if([$1],,grecs,$1)/src/Makefile:m4_if([$1],,grecs,$1)/src/Make-shared.in) + ],[ GRECS_LDADD='$(top_builddir)/m4_if([$1],,grecs,$1)/src/libgrecs.a' - AC_CONFIG_FILES(m4_if([$1],,grecs,$1)/src/Makefile:m4_if([$1],,grecs,$1)/src/Make-noinst.in) - ]) + AC_CONFIG_FILES(m4_if([$1],,grecs,$1)/src/Makefile:m4_if([$1],,grecs,$1)/src/Make-static.in) + ]) AC_CONFIG_FILES(m4_if([$1],,grecs,$1)/Makefile) ]) diff --git a/doc/GRECS_SETUP.3 b/doc/GRECS_SETUP.3 index 23c0ad5..af0f8e0 100644 --- a/doc/GRECS_SETUP.3 +++ b/doc/GRECS_SETUP.3 @@ -16,7 +16,7 @@ .\" This file is part of SLB. .\" Copyright (C) 2011 Sergey Poznyakoff .\" -.TH GRECS_SETUP 3 "May 4, 2011" "GRECS" "Grecs User Reference" +.TH GRECS_SETUP 3 "May 5, 2011" "GRECS" "Grecs User Reference" .SH NAME GRECS_SETUP \- Initialize \fBgrecs\fR submodule. .SH SYNOPSIS @@ -53,6 +53,11 @@ Disable the use of preprocessor. Create and install shared library \fBlibgrecs.so\fR. Install the documentation as well. .TP +.B shared +Create a shared convenience library. By default, a static library is +created. Use this option if you want to incorporate grecs into another +shared library. +.TP .B std-pp-setup Install the standard \fBpp-setup\fR file. .TP diff --git a/doc/grecs_format_locus.3 b/doc/grecs_format_locus.3 index 3803c2b..90ffa03 100644 --- a/doc/grecs_format_locus.3 +++ b/doc/grecs_format_locus.3 @@ -29,7 +29,7 @@ grecs_format_locus \- format and output source file location human-readable form and outputs it to file \fBfp\fR. .PP The location is output as follows: the file name, followed by a -semicolon, followed by line number and another semicolon. +semicolon, followed by the line number. .PP If \fIlocus\fR is \fBNULL\fR, \fBgrecs_format_locus\fR returns without doing anything. diff --git a/doc/grecs_format_node.3 b/doc/grecs_format_node.3 index d1d8b02..76cebec 100644 --- a/doc/grecs_format_node.3 +++ b/doc/grecs_format_node.3 @@ -58,10 +58,14 @@ when necessary, i.e. if it contains white space, quotes or special characters. This option is useful only together with \fBGRECS_NODE_FLAG_VALUE\fR. .TP +.B GRECS_NODE_FLAG_NOQUOTE +Never quote values. If both \fBGRECS_NODE_FLAG_QUOTE\fR and +\fBGRECS_NODE_FLAG_NOQUOTE\fR are given, the former takes precedence +over the latter. +.TP .B GRECS_NODE_FLAG_QUOTE_HEX Print non-printable characters as C hex escapets. This option is -useful only together with \fBGRECS_NODE_FLAG_QUOTE\fR and -\fBGRECS_NODE_FLAG_VALUE\fR. +ignored if \fBGRECS_NODE_FLAG_NOQUOTE\fR is set. .TP .B GRECS_NODE_FLAG_DEFAULT Same as diff --git a/src/.gitignore b/src/.gitignore index bf5d140..9ef1b57 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -2,5 +2,6 @@ grecs-gram.c grecs-gram.h grecs-gram.output grecs-lex.c -Make-noinst.in Make-inst.in +Make-shared.in +Make-static.in diff --git a/src/Make-shared.am b/src/Make-shared.am new file mode 100644 index 0000000..bbf25d4 --- /dev/null +++ b/src/Make-shared.am @@ -0,0 +1,18 @@ +# This file is part of grecs - Gray's Extensible Configuration System +# Copyright (C) 2007, 2009-2011 Sergey Poznyakoff +# +# Grecs 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, or (at your option) +# any later version. +# +# Grecs 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 Grecs. If not, see <http://www.gnu.org/licenses/>. +include Make.am +noinst_LT_LIBRARIES=libgrecs.la +libgrecs_la_SOURCES = $(GRECS_SRC) diff --git a/src/Make-noinst.am b/src/Make-static.am index bf4f7ce..bf4f7ce 100644 --- a/src/Make-noinst.am +++ b/src/Make-static.am diff --git a/src/Make.am b/src/Make.am index e655767..fb3b80b 100644 --- a/src/Make.am +++ b/src/Make.am @@ -27,10 +27,11 @@ GRECS_SRC = \ text.c\ tree.c\ grecs.h\ + version.c\ wordsplit.c\ wordsplit.h -EXTRA_DIST=grecs-gram.h $(PP_SETUP_FILE) Make.am Make-inst.am Make-noinst.am +EXTRA_DIST=grecs-gram.h $(PP_SETUP_FILE) Make.am Make-inst.am Make-shared.am Make-static.am INCLUDES = -I$(srcdir) @GRECS_INCLUDES@ AM_YFLAGS = -dtv @@ -26,6 +26,7 @@ static void default_print_diag(grecs_locus_t *locus, int err, int errcode, const char *msg) { + fflush(stdout); if (locus) fprintf(stderr, "%s:%d: ", locus->file, locus->line); if (!err) diff --git a/src/format.c b/src/format.c index 2c97b72..6e33521 100644 --- a/src/format.c +++ b/src/format.c @@ -188,7 +188,7 @@ void grecs_format_locus(grecs_locus_t *locus, FILE *fp) { if (locus) - fprintf(fp, "%s:%d:", locus->file, locus->line); + fprintf(fp, "%s:%d", locus->file, locus->line); } void @@ -222,6 +222,8 @@ grecs_format_value(struct grecs_value *val, int flags, FILE *fp) &need_quote); if (flags & GRECS_NODE_FLAG_QUOTE) need_quote = 1; + else if (flags & GRECS_NODE_FLAG_NOQUOTE) + need_quote = 0; if (need_quote) { char *cbuf = grecs_malloc(clen + 1); wordsplit_c_quote_copy(cbuf, val->v.string, @@ -257,6 +259,8 @@ grecs_format_value(struct grecs_value *val, int flags, FILE *fp) void grecs_format_node(struct grecs_node *node, int flags, FILE *fp) { + const char *delim_str = NULL; + if (!flags) flags = GRECS_NODE_FLAG_DEFAULT; switch (node->type) { @@ -271,15 +275,19 @@ grecs_format_node(struct grecs_node *node, int flags, FILE *fp) case grecs_node_stmt: if (flags & GRECS_NODE_FLAG_LOCUS) { grecs_format_locus(&node->locus, fp); - fputc(' ', fp); + delim_str = ": "; } if (flags & GRECS_NODE_FLAG_PATH) { + if (delim_str) + fprintf(fp, "%s", delim_str); grecs_format_node_path(node, flags, fp); - fputc(':', fp); - fputc(' ', fp); + delim_str = ": "; } - if (flags & GRECS_NODE_FLAG_VALUE) + if (flags & GRECS_NODE_FLAG_VALUE) { + if (delim_str) + fprintf(fp, "%s", delim_str); grecs_format_value(&node->value, flags, fp); + } } } diff --git a/src/grecs.h b/src/grecs.h index c408aa0..b6ac85c 100644 --- a/src/grecs.h +++ b/src/grecs.h @@ -37,6 +37,15 @@ # define N_(s) s #endif +struct grecs_version_info { + const char *package; + const char *version; + int major; + int minor; + int patch; + char *suffix; +}; + typedef struct { char *file; int line; @@ -149,6 +158,9 @@ struct grecs_sockaddr { struct sockaddr *sa; }; +void grecs_version(struct grecs_version_info *pv); +int grecs_version_cmp(const char *vstr); + extern void *(*grecs_malloc_fun)(size_t size); extern void *(*grecs_realloc_fun)(void *ptr, size_t size); extern void (*grecs_alloc_die_fun)(void); @@ -236,7 +248,8 @@ void grecs_format_value(struct grecs_value *val, int flags, FILE *fp); #define GRECS_NODE_FLAG_PATH 0x0200 #define GRECS_NODE_FLAG_VALUE 0x0400 #define GRECS_NODE_FLAG_QUOTE 0x0800 -#define GRECS_NODE_FLAG_QUOTE_HEX 0x1000 +#define GRECS_NODE_FLAG_NOQUOTE 0x1000 +#define GRECS_NODE_FLAG_QUOTE_HEX 0x2000 #define GRECS_NODE_FLAG_DEFAULT \ (GRECS_NODE_FLAG_PATH|GRECS_NODE_FLAG_VALUE|GRECS_NODE_FLAG_QUOTE) void grecs_format_node(struct grecs_node *node, int flags, FILE *fp); diff --git a/src/version.c b/src/version.c new file mode 100644 index 0000000..d34b8b5 --- /dev/null +++ b/src/version.c @@ -0,0 +1,86 @@ +/* grecs - Gray's Extensible Configuration System + Copyright (C) 2007-2011 Sergey Poznyakoff + + Grecs 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. + + Grecs 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 Grecs. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <grecs.h> +#include <string.h> +#include <ctype.h> + +void +grecs_version(struct grecs_version_info *pv) +{ + char *p; + memset(pv, 0, sizeof(*pv)); + pv->package = PACKAGE_NAME; + pv->version = PACKAGE_VERSION; + pv->major = strtoul(pv->version, &p, 10); + if (*p && *p == '.') { + pv->minor = strtoul(p + 1, &p, 10); + if (*p && *p == '.') { + char *q; + + pv->patch = strtoul(p + 1, &q, 10); + if (q == p + 1) + pv->patch = 0; + else + p = q; + } + } + pv->suffix = p; +} + +int +grecs_version_cmp(const char *vstr) +{ + struct grecs_version_info v; + char *p; + unsigned long n; + size_t len; + int check; + + if (!vstr) + return -1; + grecs_version(&v); + len = strcspn(vstr, " \t"); + if (vstr[len]) { + if (len != strlen(v.package) || memcmp(v.package, vstr, len)) + return 1; + for (vstr += len; *vstr && isspace(*vstr); vstr++) + ; + } + if (!*vstr) + return 1; + n = strtoul(vstr, &p, 10); + if (n > v.major) + return 1; + check = n == v.major; + if (*p && *p == '.') { + n = strtoul(p + 1, &p, 10); + if (check && n > v.minor) + return 1; + check = n == v.minor; + if (*p && *p == '.') { + n = strtoul(p + 1, &p, 10); + if (check && n > v.patch) + return 1; + } + } + if (*p && (!v.suffix || strcmp(p, v.suffix))) + return 1; + return 0; +} diff --git a/tests/.gitignore b/tests/.gitignore index 3110c40..0095883 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -3,6 +3,7 @@ atlocal gcffmt gcfpeek gcfset +gcfver package.m4 testsuite testsuite.log diff --git a/tests/Makefile.am b/tests/Makefile.am index aeea22b..05a5548 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -31,6 +31,7 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \ echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \ echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \ + echo 'm4_define([GRECS_VERCMP_AT], [@GRECS_VERCMP_AT@])'; \ } >$(srcdir)/package.m4 # @@ -49,7 +50,8 @@ TESTSUITE_AT = \ peek02.at\ peek03.at\ set.at\ - testsuite.at + testsuite.at\ + @GRECS_VERCMP_AT@ TESTSUITE = $(srcdir)/testsuite M4=m4 @@ -75,7 +77,8 @@ check-local: atconfig atlocal $(TESTSUITE) noinst_PROGRAMS = \ gcffmt\ gcfpeek\ - gcfset + gcfset\ + gcfver LDADD=@GRECS_LDADD@ INCLUDES = -I$(top_srcdir)/@GRECS_SUBDIR@/src diff --git a/tests/gcfver.c b/tests/gcfver.c new file mode 100644 index 0000000..990d920 --- /dev/null +++ b/tests/gcfver.c @@ -0,0 +1,47 @@ +/* grecs - Gray's Extensible Configuration System + Copyright (C) 2007-2011 Sergey Poznyakoff + + Grecs 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. + + Grecs 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 Grecs. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include "grecs.h" + +int +main(int argc, char **argv) +{ + struct grecs_version_info vinfo; + + if (argc > 2) { + fprintf(stderr, "usage: %s [version]\n", argv[0]); + exit(1); + } + if (argc == 2) + exit(grecs_version_cmp(argv[1]) ? 2 : 0); + /* Default action: */ + grecs_version(&vinfo); + printf("package: %s\n", vinfo.package); + printf("version: %s\n", vinfo.version); + printf("major: %d\n", vinfo.major); + printf("minor: %d\n", vinfo.minor); + printf("patch: %d\n", vinfo.patch); + printf("suffix:"); + if (vinfo.suffix && vinfo.suffix[0]) + printf(" %s", vinfo.suffix); + putchar('\n'); + exit(0); +} + + diff --git a/tests/testsuite.at b/tests/testsuite.at index 3b0ec84..e60b82d 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -51,4 +51,7 @@ m4_include([peek03.at]) m4_include([cfhelp.at]) m4_include([set.at]) + +m4_if(GRECS_VERCMP_AT,,,[m4_include(GRECS_VERCMP_AT)]) + # End of testsuite.at diff --git a/tests/vercmp.at b/tests/vercmp.at new file mode 100644 index 0000000..9ef495a --- /dev/null +++ b/tests/vercmp.at @@ -0,0 +1,63 @@ +# This file is part of grecs -*- Autotest -*- +# Copyright (C) 2007, 2009-2011 Sergey Poznyakoff +# +# Grecs 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, or (at your option) +# any later version. +# +# Grecs 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 Grecs. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP(Version comparator) +AT_KEYWORDS(vercmp) + +dnl Split Package version into major, minor, patchlevel and suffix + +m4_define([V_MAJOR],[m4_bpatsubst(AT_PACKAGE_VERSION,[\..*])]) +m4_define([V_MINOR],[m4_bpatsubst(AT_PACKAGE_VERSION,[[0-9]+\.\([0-9]+\).*],\1)]) + +m4_define([V_PATCH_TMP],[m4_bpatsubst(AT_PACKAGE_VERSION,[[0-9]+\.[0-9]+\.\([0-9]+\).*],\1)]) +m4_define([V_PATCH],[m4_if(V_PATCH_TMP,AT_PACKAGE_VERSION,[0],V_PATCH_TMP)]) + +m4_pushdef([V_SUFFIX_TMP],[m4_bpatsubst(AT_PACKAGE_VERSION,[[0-9]+\.[0-9]+\(\.[0-9]+\)?])]) +m4_define([V_SUFFIX],[m4_if(V_SUFFIX_TMP,AT_PACKAGE_VERSION,,[ V_SUFFIX_TMP])]) + +dnl Join them back and see if the result matches version. +m4_define([V_OK], +[m4_if(V_MAJOR.V_MINOR[]m4_if(V_PATCH_TMP,AT_PACKAGE_VERSION,,V_PATCH_TMP)dnl +m4_if(V_SUFFIX_TMP,AT_PACKAGE_VERSION,,V_SUFFIX_TMP),AT_PACKAGE_VERSION, +[exit 0], +AT_SKIP_TEST)]) + +AT_CHECK([V_OK]) + +AT_CHECK([gcfver], +[0], +[package: AT_PACKAGE_NAME +version: AT_PACKAGE_VERSION +major: V_MAJOR +minor: V_MINOR +patch: V_PATCH +suffix:V_SUFFIX +]) + +AT_CHECK([gcfver AT_PACKAGE_VERSION], [0]) +AT_CHECK([gcfver "AT_PACKAGE_NAME AT_PACKAGE_VERSION"], [0]) +AT_CHECK([gcfver AT_PACKAGE_VERSION.[foo]], [2]) +AT_CHECK([gcfver "[foo] AT_PACKAGE_VERSION"], [2]) +AT_CHECK([gcfver V_MAJOR], [0]) +AT_CHECK([gcfver V_MAJOR.V_MINOR], [0]) +AT_CHECK([gcfver m4_eval(V_MAJOR+1)], [2]) +AT_CHECK([gcfver V_MAJOR.m4_eval(V_MINOR+1)], [2]) +m4_if(V_MAJOR,0,, + [AT_CHECK([gcfver m4_eval(V_MAJOR-1)],[0]) + AT_CHECK([gcfver m4_eval(V_MAJOR-1).m4_eval(V_MINOR+1)],[0]) + ]) + +AT_CLEANUP |