+2007-05-20 Joel E. Denny <jdenny@ces.clemson.edu>
+
+ Extend the front-end API for %define variables to more completely
+ mirror the back-end. This will be useful in the future.
+ * data/bison.m4 (b4_percent_define_get, b4_percent_define_ifdef):
+ Update comments to mention the new front-end counterparts of these
+ macros.
+ * src/muscle_tab.c (MUSCLE_COMMON_DECODE): New macro with common code
+ for muscle_string_decode and muscle_location_decode.
+ (muscle_string_decode): New static function.
+ (muscle_location_decode): Use MUSCLE_COMMON_DECODE.
+ (muscle_percent_define_get, muscle_percent_define_ifdef): New
+ functions.
+ (muscle_percent_define_flag_if): Use muscle_percent_define_ifdef and
+ muscle_percent_define_get to mimic the b4_percent_define_flag_if
+ implementation more closely.
+ (muscle_percent_define_invalid_value): New function.
+ * src/muscle_tab.h (muscle_percent_define_get,
+ muscle_percent_define_ifdef, muscle_percent_define_invalid_value):
+ Prototype.
+
2007-05-07 Joel E. Denny <jdenny@ces.clemson.edu>
* NEWS (2.3a+): Mention yesterday's state-removal change.
# b4_percent_define_get(VARIABLE)
# -------------------------------
-# If the %define variable VARIABLE is defined, emit its value. Also, record
+# Mimic muscle_percent_define_get in ../src/muscle_tab.h exactly. That is, if
+# the %define variable VARIABLE is defined, emit its value. Also, record
# Bison's usage of VARIABLE by defining
# b4_percent_define_bison_variables(VARIABLE).
#
# b4_percent_define_ifdef(VARIABLE, IF-TRUE, [IF-FALSE])
# ------------------------------------------------------
-# If the %define variable VARIABLE is defined, expand IF-TRUE, else expand
+# Mimic muscle_percent_define_ifdef in ../src/muscle_tab.h exactly. That is,
+# if the %define variable VARIABLE is defined, expand IF-TRUE, else expand
# IF-FALSE. Also, record Bison's usage of VARIABLE by defining
# b4_percent_define_bison_variables(VARIABLE).
#
muscle_grow (key, "]]", "");
}
+#define MUSCLE_COMMON_DECODE(Value) \
+ case '$': \
+ aver (*++(Value) == ']'); \
+ aver (*++(Value) == '['); \
+ obstack_sgrow (&muscle_obstack, "$"); \
+ break; \
+ case '@': \
+ switch (*++(Value)) \
+ { \
+ case '@': obstack_sgrow (&muscle_obstack, "@" ); break; \
+ case '{': obstack_sgrow (&muscle_obstack, "[" ); break; \
+ case '}': obstack_sgrow (&muscle_obstack, "]" ); break; \
+ default: aver (false); break; \
+ } \
+ break; \
+ default: \
+ obstack_1grow (&muscle_obstack, *(Value)); \
+ break;
+
+/* Reverse of MUSCLE_OBSTACK_SGROW. */
+static char *
+muscle_string_decode (char const *key)
+{
+ char const *value;
+ char *value_decoded;
+ char *result;
+
+ value = muscle_find_const (key);
+ if (!value)
+ return NULL;
+ do {
+ switch (*value)
+ {
+ MUSCLE_COMMON_DECODE (value)
+ case '[':
+ case ']':
+ aver (false);
+ break;
+ }
+ } while (*value++);
+ value_decoded = obstack_finish (&muscle_obstack);
+ result = xstrdup (value_decoded);
+ obstack_free (&muscle_obstack, value_decoded);
+ return result;
+}
+
/* Reverse of muscle_location_grow. */
static location
muscle_location_decode (char const *key)
while (*++value)
switch (*value)
{
- case '$':
- aver (*++value == ']');
- aver (*++value == '[');
- obstack_sgrow (&muscle_obstack, "$");
- break;
- case '@':
- switch (*++value)
- {
- case '@': obstack_sgrow (&muscle_obstack, "@" ); break;
- case '{': obstack_sgrow (&muscle_obstack, "[" ); break;
- case '}': obstack_sgrow (&muscle_obstack, "]" ); break;
- default: aver (false); break;
- }
- break;
+ MUSCLE_COMMON_DECODE (value)
case '[':
aver (false);
break;
}
}
break;
- default:
- obstack_1grow (&muscle_obstack, *value);
- break;
}
aver (false);
return loc;
variable_loc);
}
+char *
+muscle_percent_define_get (char const *variable)
+{
+ char const *name;
+ 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, ")");
+
+ muscle_insert (usage_name, "");
+ value = muscle_string_decode (name);
+ if (!value)
+ value = xstrdup ("");
+ return value;
+}
+
+bool
+muscle_percent_define_ifdef (char const *variable)
+{
+ char const *name;
+ 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, ")");
+
+ value = muscle_find_const (name);
+ if (value)
+ {
+ muscle_insert (usage_name, "");
+ return true;
+ }
+
+ return false;
+}
+
bool
muscle_percent_define_flag_if (char const *variable)
{
char const *name;
char const *loc_name;
char const *usage_name;
- char const *value;
bool result = false;
MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
MUSCLE_USER_NAME_CONVERT (usage_name, "percent_define_bison_variables(",
variable, ")");
- value = muscle_find_const (name);
- if (value)
+ if (muscle_percent_define_ifdef (variable))
{
+ char *value = muscle_percent_define_get (variable);
if (value[0] == '\0' || 0 == strcmp (value, "true"))
result = true;
else if (0 == strcmp (value, "false"))
complain_at(muscle_location_decode (loc_name),
_("invalid value for %%define boolean variable `%s'"),
variable);
+ free (value);
}
else
fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_flag_if"),
variable);
- muscle_insert (usage_name, "");
-
return result;
}
}
}
+void
+muscle_percent_define_invalid_value (char const *variable)
+{
+ char const *loc_name;
+ MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")");
+ complain_at(muscle_location_decode (loc_name),
+ _("invalid value for %%define variable `%s'"), variable);
+}
+
+
void
muscle_percent_code_grow (char const *qualifier, location qualifier_loc,
char const *code, location code_loc)
void muscle_percent_define_insert (char const *variable, location variable_loc,
char const *value);
+/* Mimic b4_percent_define_get in ../data/bison.m4 exactly. That is, if the
+ %define variable VARIABLE is defined, return its value. Otherwise, return
+ the empty string. Also, record Bison's usage of VARIABLE by defining
+ b4_percent_define_bison_variables(VARIABLE). The caller is responsible for
+ freeing the memory of the returned string. */
+char *muscle_percent_define_get (char const *variable);
+
+/* Mimic b4_percent_define_ifdef in ../data/bison.m4 exactly. That is, if the
+ %define variable VARIABLE is defined, return true. Otherwise, return false.
+ Also, record Bison's usage of VARIABLE by defining
+ b4_percent_define_bison_variables(VARIABLE). */
+bool muscle_percent_define_ifdef (char const *variable);
+
/* Mimic b4_percent_define_flag_if in ../data/bison.m4 exactly. That is, if
the %define variable VARIABLE is defined to "" or "true", return true. If
it is defined to "false", return false. Complain if it is undefined (a
suspect that the value has yet influenced the output. */
void muscle_percent_define_default (char const *variable, char const *value);
+/* Complain that the value set for the %define variable VARIABLE is
+ invalid. */
+void muscle_percent_define_invalid_value (char const *variable);
+
/* Grow the muscle for the %code qualifier QUALIFIER appearing at QUALIFIER_LOC
in the grammar file with code CODE appearing at CODE_LOC. Record this as a
grammar occurrence of VARIABLE by invoking muscle_user_name_list_grow. */