From 7f1f40bee65a4a3d3947ad8c50b535ea0754f629 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Thu, 24 Feb 2022 22:35:50 -0500 Subject: [PATCH] Allow building against Glib 1.x. In reality, we barely depend on any glib-2 features in the tool itself (of course, the output does require it). Other than very minor additions and pointlessly renamed functions, the only real new feature is the locale-independent g_ascii_xxx case conversions. As we already have an abstraction of these in place it is very easy to just substitute a gnulib-based replacement when configure determines they are unavailable. At the moment, configure does not know how to automatically find glib-1.x, so manually setting LIBGLIB_CFLAGS and LIBGLIB_LIBS is required to build against it. This is probably fine. --- Makefile.am | 4 ++ configure.ac | 9 ++- m4/.gitignore | 1 + m4/gnulib-cache.m4 | 4 +- src/gob-strcase.c | 176 +++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 12 ++-- src/util.c | 28 ++++---- src/util.h | 35 +++++++-- 8 files changed, 241 insertions(+), 28 deletions(-) create mode 100644 src/gob-strcase.c diff --git a/Makefile.am b/Makefile.am index 8c084bc..c7ca686 100644 --- a/Makefile.am +++ b/Makefile.am @@ -47,6 +47,10 @@ gob2_SOURCES = src/main.c src/main.h src/treefuncs.c src/out.c src/util.c \ gob2_LDADD = $(LIBGLIB_LIBS) libgnu.a $(gob2_OBJECTS): $(gnulib_headers) src/treefuncs.h src/options.h +if GOB_STRCASE +gob2_SOURCES += src/gob-strcase.c +endif + man_MANS = doc/gob2.1 EXTRA_DIST += doc/makehtml.pl diff --git a/configure.ac b/configure.ac index e190000..5099990 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -dnl Copyright © 2019-2021 Nick Bowler +dnl Copyright © 2019-2022 Nick Bowler dnl dnl Based on original work Copyright © 1999-2013 Jiri (George) Lebl. dnl @@ -41,6 +41,13 @@ dnl Dependencies for test suite DX_LIB_GLIB2([], [gobject], [HAVE_GOBJECT=true], [HAVE_GOBJECT=false]) AC_SUBST([HAVE_GOBJECT]) +save_LIBS=$LIBS +LIBS="$LIBS $LIBGLIB_LIBS" +AC_CHECK_FUNCS([g_string_append_printf g_ascii_strcasecmp]) +LIBS=$save_LIBS + +AM_CONDITIONAL([GOB_STRCASE], [test x"$ac_cv_func_g_ascii_strcasecmp" = x"no"]) + AS_IF([$HAVE_GOBJECT], [AC_CACHE_CHECK([whether libgobject supports private data members], [dx_cv_libgobject_privates], diff --git a/m4/.gitignore b/m4/.gitignore index 9e206c5..ace8fd0 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -7,6 +7,7 @@ /gnulib-comp.m4 /gnulib-tool.m4 /include_next.m4 +/inline.m4 /libtool.m4 /ltoptions.m4 /ltsugar.m4 diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index 624dee6..1a2cdad 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -41,13 +41,15 @@ # --macro-prefix=gl \ # --no-vc-files \ # getopt-gnu \ -# gitlog-to-changelog +# gitlog-to-changelog \ +# inline # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) gl_MODULES([ getopt-gnu gitlog-to-changelog + inline ]) gl_AVOID([]) gl_SOURCE_BASE([lib]) diff --git a/src/gob-strcase.c b/src/gob-strcase.c new file mode 100644 index 0000000..87c59a6 --- /dev/null +++ b/src/gob-strcase.c @@ -0,0 +1,176 @@ +/* c-strcasecmp.c -- case insensitive string comparator in C locale + Copyright (C) 1998-1999, 2005-2006, 2009-2021 Free Software Foundation, Inc. + + Character handling in C locale. + Copyright (C) 2000-2003, 2006, 2008-2021 Free Software Foundation, Inc. + + Stripped down copy of gnulib c-ctype and c-strcasecmp modules for + conditional fallback use. + + 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 2, 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 . */ + +#include +#include + +#undef HAVE_G_ASCII_STRCASECMP +#include "util.h" + +/* The functions defined in this file assume the "C" locale and a character + set without diacritics (ASCII-US or EBCDIC-US or something like that). + Even if the "C" locale on a particular system is an extension of the ASCII + character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it + is ISO-8859-1), the functions in this file recognize only the ASCII + characters. */ + +#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126) +/* The character set is ASCII or one of its variants or extensions, not EBCDIC. + Testing the value of '\n' and '\r' is not relevant. */ +# define C_CTYPE_ASCII 1 +#elif ! (' ' == '\x40' && '0' == '\xf0' \ + && 'A' == '\xc1' && 'J' == '\xd1' && 'S' == '\xe2' \ + && 'a' == '\x81' && 'j' == '\x91' && 's' == '\xa2') +# error "Only ASCII and EBCDIC are supported" +#endif + +#if 'A' < 0 +# error "EBCDIC and char is signed -- not supported" +#endif + +/* Cases for lowercase hex letters, and lowercase letters, all offset by N. */ + +#define C_CTYPE_LOWER_A_THRU_F_N(N) \ + case 'a' + (N): case 'b' + (N): case 'c' + (N): case 'd' + (N): \ + case 'e' + (N): case 'f' + (N) +#define C_CTYPE_LOWER_N(N) \ + C_CTYPE_LOWER_A_THRU_F_N(N): \ + case 'g' + (N): case 'h' + (N): case 'i' + (N): case 'j' + (N): \ + case 'k' + (N): case 'l' + (N): case 'm' + (N): case 'n' + (N): \ + case 'o' + (N): case 'p' + (N): case 'q' + (N): case 'r' + (N): \ + case 's' + (N): case 't' + (N): case 'u' + (N): case 'v' + (N): \ + case 'w' + (N): case 'x' + (N): case 'y' + (N): case 'z' + (N) + +#define C_CTYPE_LOWER C_CTYPE_LOWER_N(0) +#define C_CTYPE_UPPER C_CTYPE_LOWER_N ('A' - 'a') + + +/* Function definitions. */ + +/* Unlike the functions in , which require an argument in the range + of the 'unsigned char' type, the functions here operate on values that are + in the 'unsigned char' range or in the 'char' range. In other words, + when you have a 'char' value, you need to cast it before using it as + argument to a function: + + const char *s = ...; + if (isalpha ((unsigned char) *s)) ... + + but you don't need to cast it for the functions defined in this file: + + const char *s = ...; + if (c_isalpha (*s)) ... + */ + +static int c_tolower(int c) +{ + switch (c) { + C_CTYPE_UPPER: + return c - 'A' + 'a'; + default: + return c; + } +} + +static int c_toupper(int c) +{ + switch (c) { + C_CTYPE_LOWER: + return c - 'a' + 'A'; + default: + return c; + } +} + +char *gob_strup(char *str) +{ + char *s; + + for (s = str; *s; s++) + *s = c_toupper(*s); + + return str; +} + +char *gob_strdown(char *str) +{ + char *s; + + for (s = str; *s; s++) + *s = c_tolower(*s); + + return str; +} + +int gob_strcasecmp(const char *s1, const char *s2) +{ + register const unsigned char *p1 = (const unsigned char *)s1; + register const unsigned char *p2 = (const unsigned char *)s2; + unsigned char c1, c2; + + if (p1 == p2) + return 0; + + do { + c1 = c_tolower (*p1); + c2 = c_tolower (*p2); + + if (c1 == '\0') + break; + + ++p1; + ++p2; + } while (c1 == c2); + + if (UCHAR_MAX <= INT_MAX) { + return c1 - c2; + } else { + /* + * On machines where 'char' and 'int' are types of the + * same size, the difference of two 'unsigned char' values + * - including the sign bit - doesn't fit in an 'int'. + */ + return _GL_CMP (c1, c2); + } +} diff --git a/src/main.c b/src/main.c index 0e6c55c..4aea007 100644 --- a/src/main.c +++ b/src/main.c @@ -153,9 +153,9 @@ make_bases (void) filebase = replace_sep (((Class *)class)->otype, file_sep); gob_strdown (filebase); - if (output_dir != NULL && - output_dir[0] != '\0') { - fullfilebase = g_build_filename (output_dir, filebase, NULL); + if (output_dir != NULL && output_dir[0] != '\0') { + fullfilebase = g_strdup_printf("%s%c%s", output_dir, + G_DIR_SEPARATOR, filebase); } else { fullfilebase = g_strdup (filebase); } @@ -3165,6 +3165,7 @@ static char * get_arg_names_for_macro (Method *m) { const char *sep; + char *ret; GList *li; GString *gs = g_string_new(NULL); sep = ""; @@ -3173,7 +3174,10 @@ get_arg_names_for_macro (Method *m) g_string_append_printf(gs, "%s___%s", sep, arg->name); sep = ","; } - return g_string_free (gs, FALSE); + + ret = gs->str; + g_string_free(gs, FALSE); + return ret; } static gboolean method_is_void(Method *m) diff --git a/src/util.c b/src/util.c index d040ee4..ddf9485 100644 --- a/src/util.c +++ b/src/util.c @@ -1,6 +1,7 @@ /* GOB C Preprocessor * Copyright (C) 1999-2000 the Free Software Foundation. * Copyright (C) 2000 Eazel, Inc. + * Copyright (C) 2022 Nick Bowler * * Author: George Lebl * @@ -356,7 +357,7 @@ setup_special_array(Class *c, gboolean *special_array) char * get_type (const Type *t, gboolean postfix_to_stars) { - char *s; + char *ret, *s; int i; int extra; GString *gs; @@ -383,35 +384,32 @@ get_type (const Type *t, gboolean postfix_to_stars) g_string_append_c (gs, '*'); g_string_append_c (gs, ' '); } - - return g_string_free (gs, FALSE); + ret = gs->str; + g_string_free(gs, FALSE); + return ret; } -char * -gob_strup (char *str) +#if HAVE_G_ASCII_STRCASECMP +char *gob_strup(char *str) { char *s; + for (s = str; *s; s++) - *s = g_ascii_toupper (*s); + *s = g_ascii_toupper(*s); return str; } -char * -gob_strdown (char *str) +char *gob_strdown(char *str) { char *s; + for (s = str; *s; s++) - *s = g_ascii_tolower (*s); + *s = g_ascii_tolower(*s); return str; } - -int -gob_strcasecmp(const char *s1, const char *s2) -{ - return g_ascii_strcasecmp(s1, s2); -} +#endif char * gob_str_delete_quotes(char *str) diff --git a/src/util.h b/src/util.h index bb69ed2..03a12d1 100644 --- a/src/util.h +++ b/src/util.h @@ -1,6 +1,7 @@ /* GOB C Preprocessor * Copyright (C) 1999-2000 the Free Software Foundation. * Copyright (C) 2000 Eazel, Inc. + * Copyright (C) 2022 Nick Bowler * * Author: George Lebl * @@ -23,6 +24,11 @@ #ifndef UTIL_H #define UTIL_H +#include + +struct _Class; +struct _Type; + enum { GOB_WARN, GOB_ERROR @@ -38,10 +44,24 @@ char * remove_sep(const char *base); /* replace the : separator from a typename with a different character*/ char * replace_sep(const char *base, char r); -char * gob_strup (char *s); -char * gob_strdown (char *s); -char * gob_str_delete_quotes(char *str); +#if !HAVE_G_STRING_APPEND_PRINTF +# define g_string_append_printf g_string_sprintfa +# define g_string_printf g_string_sprintf +#endif + +char *gob_strup(char *s); +char *gob_strdown(char *s); + +#if HAVE_G_ASCII_STRCASECMP +static inline int gob_strcasecmp(const char *s1, const char *s2) +{ + return g_ascii_strcasecmp(s1, s2); +} +#else int gob_strcasecmp(const char *s1, const char *s2); +#endif + +char * gob_str_delete_quotes(char *str); /*separate the namespace part and then replace rest of separators with r*/ @@ -52,9 +72,9 @@ void separns_replace_sep(const char *base, char **ns, char **name, char r); char * make_pre_macro(const char *base,const char *pre); /* get a name usable for a cast from a GObject (without G_TYPE_)*/ -const char * get_cast (const char *type, gboolean simple_only); -Type * get_tree_type (const char *type, gboolean simple_only); -char * get_type (const Type *t, gboolean postfix_to_stars); +const char *get_cast(const char *type, gboolean simple_only); +struct _Type *get_tree_type(const char *type, gboolean simple_only); +char *get_type(const struct _Type *t, gboolean postfix_to_stars); enum { SPECIAL_2POINTER, @@ -62,8 +82,9 @@ enum { SPECIAL_INT_POINTER, SPECIAL_LAST }; + /* returns TRUE if there are any special types at all */ -gboolean setup_special_array(Class *c, gboolean *special_array); +gboolean setup_special_array(struct _Class *c, gboolean *special_array); char * make_me_type (const char *type, const char *alt); -- 2.43.2