From 10659d0ec997368fe57712a7c564795c530ba0c2 Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Wed, 7 Oct 2009 23:09:43 -0400 Subject: [PATCH] Minor code cleanup. * src/muscle-tab.c (MUSCLE_USER_NAME_CONVERT): Remove macro and replace all uses with UNIQSTR_CONCAT. * src/uniqstr.c (uniqstr_vsprintf): New function. * src/uniqstr.h (uniqstr_vsprintf): Add prototype. (UNIQSTR_CONCAT, UNIQSTR_GEN_FORMAT, UNIQSTR_GEN_FORMAT_): New macros. --- ChangeLog | 10 ++++++++ src/muscle-tab.c | 66 ++++++++++++++++++++---------------------------- src/uniqstr.c | 16 ++++++++++++ src/uniqstr.h | 43 +++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 39 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5bbab03a..219d9b9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2009-10-07 Joel E. Denny + + Minor code cleanup. + * src/muscle-tab.c (MUSCLE_USER_NAME_CONVERT): Remove macro and + replace all uses with UNIQSTR_CONCAT. + * src/uniqstr.c (uniqstr_vsprintf): New function. + * src/uniqstr.h (uniqstr_vsprintf): Add prototype. + (UNIQSTR_CONCAT, UNIQSTR_GEN_FORMAT, UNIQSTR_GEN_FORMAT_): New + macros. + 2009-10-06 Joel E. Denny * TODO (Complaint submessage indentation): New. diff --git a/src/muscle-tab.c b/src/muscle-tab.c index bfb78036..455515b0 100644 --- a/src/muscle-tab.c +++ b/src/muscle-tab.c @@ -413,18 +413,6 @@ muscle_percent_variable_update (char const *variable) return variable; } -#define MUSCLE_USER_NAME_CONVERT(NAME, PREFIX, USER_NAME, SUFFIX) \ -do { \ - char *tmp; \ - size_t length = strlen ((USER_NAME)); \ - tmp = xmalloc (sizeof (PREFIX) - 1 + length + sizeof (SUFFIX)); \ - strcpy (tmp, (PREFIX)); \ - strcpy (tmp + sizeof (PREFIX) - 1, (USER_NAME)); \ - strcpy (tmp + sizeof (PREFIX) - 1 + length, (SUFFIX)); \ - (NAME) = uniqstr_new (tmp); \ - free (tmp); \ -} while (0) - void muscle_percent_define_insert (char const *variable, location variable_loc, char const *value, @@ -438,11 +426,11 @@ muscle_percent_define_insert (char const *variable, location variable_loc, /* Permit certain names with underscores for backward compatibility. */ variable = muscle_percent_variable_update (variable); - MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")"); - MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")"); - MUSCLE_USER_NAME_CONVERT (syncline_name, - "percent_define_syncline(", variable, ")"); - MUSCLE_USER_NAME_CONVERT (how_name, "percent_define_how(", variable, ")"); + name = UNIQSTR_CONCAT ("percent_define(", variable, ")"); + loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")"); + syncline_name = + UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")"); + how_name = UNIQSTR_CONCAT ("percent_define_how(", variable, ")"); /* Command-line options are processed before the grammar file. */ if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE @@ -476,7 +464,7 @@ muscle_percent_define_ensure (char const *variable, location loc, { char const *val = value ? "" : "false"; char const *name; - MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")"); + name = UNIQSTR_CONCAT ("percent_define(", variable, ")"); /* %pure-parser is deprecated in favor of `%define api.pure', so use `%define api.pure' in a backward-compatible manner here. First, @@ -499,9 +487,9 @@ muscle_percent_define_get (char const *variable) char const *usage_name; char *value; - MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")"); - MUSCLE_USER_NAME_CONVERT (usage_name, "percent_define_bison_variables(", - variable, ")"); + name = UNIQSTR_CONCAT ("percent_define(", variable, ")"); + usage_name = UNIQSTR_CONCAT ("percent_define_bison_variables(", + variable, ")"); muscle_insert (usage_name, ""); value = muscle_string_decode (name); @@ -514,10 +502,10 @@ location muscle_percent_define_get_loc (char const *variable) { char const *loc_name; - MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")"); + loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")"); if (!muscle_find_const (loc_name)) - fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_get_loc"), - variable); + fatal(_("undefined %%define variable `%s' passed to" + " muscle_percent_define_get_loc"), variable); return muscle_location_decode (loc_name); } @@ -526,12 +514,12 @@ muscle_percent_define_get_syncline (char const *variable) { char const *syncline_name; char const *syncline; - MUSCLE_USER_NAME_CONVERT (syncline_name, - "percent_define_syncline(", variable, ")"); + syncline_name = + UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")"); syncline = muscle_find_const (syncline_name); if (!syncline) - fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_get_syncline"), - variable); + fatal(_("undefined %%define variable `%s' passed to" + " muscle_percent_define_get_syncline"), variable); return syncline; } @@ -542,9 +530,9 @@ muscle_percent_define_ifdef (char const *variable) char const *usage_name; char const *value; - MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")"); - MUSCLE_USER_NAME_CONVERT (usage_name, "percent_define_bison_variables(", - variable, ")"); + name = UNIQSTR_CONCAT ("percent_define(", variable, ")"); + usage_name = + UNIQSTR_CONCAT ("percent_define_bison_variables(", variable, ")"); value = muscle_find_const (name); if (value) @@ -562,8 +550,8 @@ muscle_percent_define_flag_if (char const *variable) char const *invalid_boolean_name; bool result = false; - MUSCLE_USER_NAME_CONVERT (invalid_boolean_name, - "percent_define_invalid_boolean(", variable, ")"); + invalid_boolean_name = + UNIQSTR_CONCAT ("percent_define_invalid_boolean(", variable, ")"); if (muscle_percent_define_ifdef (variable)) { @@ -594,10 +582,10 @@ muscle_percent_define_default (char const *variable, char const *value) char const *name; char const *loc_name; char const *syncline_name; - MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")"); - MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")"); - MUSCLE_USER_NAME_CONVERT (syncline_name, - "percent_define_syncline(", variable, ")"); + name = UNIQSTR_CONCAT ("percent_define(", variable, ")"); + loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")"); + syncline_name = + UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")"); if (!muscle_find_const (name)) { location loc; @@ -620,7 +608,7 @@ muscle_percent_define_check_values (char const * const *values) char const *name; char *value; - MUSCLE_USER_NAME_CONVERT (name, "percent_define(", *variablep, ")"); + name = UNIQSTR_CONCAT ("percent_define(", *variablep, ")"); value = muscle_string_decode (name); if (value) @@ -658,7 +646,7 @@ muscle_percent_code_grow (char const *qualifier, location qualifier_loc, char const *code, location code_loc) { char const *name; - MUSCLE_USER_NAME_CONVERT (name, "percent_code(", qualifier, ")"); + name = UNIQSTR_CONCAT ("percent_code(", qualifier, ")"); muscle_code_grow (name, code, code_loc); muscle_user_name_list_grow ("percent_code_user_qualifiers", qualifier, qualifier_loc); diff --git a/src/uniqstr.c b/src/uniqstr.c index 78b8a98d..ed8f79a7 100644 --- a/src/uniqstr.c +++ b/src/uniqstr.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "uniqstr.h" @@ -53,6 +54,21 @@ uniqstr_new (char const *str) return res; } +uniqstr +uniqstr_vsprintf (char const *format, ...) +{ + va_list args; + size_t length; + va_start (args, format); + length = vsnprintf (NULL, 0, format, args); + va_end (args); + + char res[length + 1]; + va_start (args, format); + vsprintf (res, format, args); + va_end (args); + return uniqstr_new (res); +} /*------------------------------. | Abort if S is not a uniqstr. | diff --git a/src/uniqstr.h b/src/uniqstr.h index 04600e94..2f9fce03 100644 --- a/src/uniqstr.h +++ b/src/uniqstr.h @@ -29,6 +29,12 @@ typedef char const *uniqstr; /* Return the uniqstr for STR. */ uniqstr uniqstr_new (char const *str); +/* Return a uniqstr built by vsprintf. In order to simply concatenate + strings, use UNIQSTR_CONCAT, which is a convenient wrapper around + this function. */ +uniqstr uniqstr_vsprintf (char const *format, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); + /* Two uniqstr values have the same value iff they are the same. */ #define UNIQSTR_EQ(USTR1, USTR2) ((USTR1) == (USTR2)) @@ -52,4 +58,41 @@ void uniqstrs_free (void); /* Report them all. */ void uniqstrs_print (void); +/*----------------. +| Concatenation. | +`----------------*/ + +/* Concatenate at most 20 strings and return a uniqstr. The goal of + this macro is to make the caller's code a little more succinct + without a trivial uniqstr_vsprintf format string to maintain + (for example, "%s%s%s") while still benefitting from gcc's type + checking. Unfortunately, because of the missing format string in the + macro invocation, the argument number reported by gcc for a bad + argument type is 1 too large. */ +#define UNIQSTR_CONCAT(...) \ + uniqstr_vsprintf (UNIQSTR_GEN_FORMAT (__VA_ARGS__, \ + "%s", "%s", "%s", "%s", "%s", \ + "%s", "%s", "%s", "%s", "%s", \ + "%s", "%s", "%s", "%s", "%s", \ + "%s", "%s", "%s", "%s", "%s"), \ + __VA_ARGS__) + +#define UNIQSTR_GEN_FORMAT(F1, F2, F3, F4, F5, \ + F6, F7, F8, F9, F10, \ + F11, F12, F13, F14, F15, \ + F16, F17, F18, F19, F20, \ + ...) \ + UNIQSTR_GEN_FORMAT_ (__VA_ARGS__, \ + "", "", "", "", "", \ + "", "", "", "", "", \ + "", "", "", "", "", \ + "", "", "", "", "") + +#define UNIQSTR_GEN_FORMAT_(F1, F2, F3, F4, F5, \ + F6, F7, F8, F9, F10, \ + F11, F12, F13, F14, F15, \ + F16, F17, F18, F19, F20, ...) \ + F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 \ + F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 + #endif /* ! defined UNIQSTR_H_ */ -- 2.45.2