maint: summarize highlights of 1.4.18 release
[m4/ericb.git] / m4 / utility.c
blob2063c6a39a190d1fb80176cf5d364195a8c2d5e7
1 /* GNU m4 -- A simple macro processor
2 Copyright (C) 1989-1994, 1998-1999, 2003, 2006-2010, 2013-2014, 2017
3 Free Software Foundation, Inc.
5 This file is part of GNU M4.
7 GNU M4 is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU M4 is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <config.h>
23 #include "m4private.h"
25 #include "exitfail.h"
26 #include "progname.h"
27 #include "quotearg.h"
28 #include "verror.h"
29 #include "xvasprintf.h"
31 static const char *skip_space (m4 *, const char *);
35 /* Give friendly warnings if a builtin macro is passed an
36 inappropriate number of arguments. MIN is the 0-based minimum
37 number of acceptable arguments, MAX is the 0-based maximum number
38 or UINT_MAX if not applicable, and SIDE_EFFECT is true if the macro
39 has side effects even if min is not satisfied. ARGC is the 1-based
40 count of supplied arguments, and CALLER is the name of the macro.
41 Return true if the macro is guaranteed to expand to the empty
42 string, false otherwise. */
43 bool
44 m4_bad_argc (m4 *context, size_t argc, const m4_call_info *caller, size_t min,
45 size_t max, bool side_effect)
47 if (argc - 1 < min)
49 m4_warn (context, 0, caller, _("too few arguments: %zu < %zu"),
50 argc - 1, min);
51 return !side_effect;
54 if (argc - 1 > max)
56 m4_warn (context, 0, caller, _("extra arguments ignored: %zu > %zu"),
57 argc - 1, max);
60 return false;
63 static const char *
64 skip_space (m4 *context, const char *arg)
66 while (m4_has_syntax (M4SYNTAX, *arg, M4_SYNTAX_SPACE))
67 arg++;
68 return arg;
71 /* The function m4_numeric_arg () converts ARG of length LEN to an int
72 pointed to by VALUEP. If the conversion fails, print error message
73 for CALLER. Return true iff conversion succeeds. */
74 /* FIXME: Convert this to use gnulib's xstrtoimax, xstrtoumax.
75 Otherwise, we are arbitrarily limiting integer values. */
76 bool
77 m4_numeric_arg (m4 *context, const m4_call_info *caller, const char *arg,
78 size_t len, int *valuep)
80 char *endp;
82 if (!len)
84 *valuep = 0;
85 m4_warn (context, 0, caller, _("empty string treated as 0"));
87 else
89 const char *str = skip_space (context, arg);
90 *valuep = strtol (str, &endp, 10);
91 if (endp - arg != len)
93 m4_warn (context, 0, caller, _("non-numeric argument %s"),
94 quotearg_style_mem (locale_quoting_style, arg, len));
95 return false;
97 if (str != arg)
98 m4_warn (context, 0, caller, _("leading whitespace ignored"));
99 else if (errno == ERANGE)
100 m4_warn (context, 0, caller, _("numeric overflow detected"));
102 return true;
105 /* Parse ARG of length LEN as a truth value. If ARG is NUL, use ""
106 instead; otherwise, ARG must have a NUL-terminator (even if it also
107 has embedded NUL). If LEN is SIZE_MAX, use the string length of
108 ARG. If unrecognized, issue a warning on behalf of CALLER and
109 return PREVIOUS; otherwise return the parsed value. */
110 bool
111 m4_parse_truth_arg (m4 *context, const m4_call_info *caller, const char *arg,
112 size_t len, bool previous)
114 /* 0, no, off, blank... */
115 if (!arg || len == 0
116 || arg[0] == '0'
117 || arg[0] == 'n' || arg[0] == 'N'
118 || ((arg[0] == 'o' || arg[0] == 'O')
119 && (arg[1] == 'f' || arg[1] == 'F')))
120 return false;
121 /* 1, yes, on... */
122 if (arg[0] == '1'
123 || arg[0] == 'y' || arg[0] == 'Y'
124 || ((arg[0] == 'o' || arg[0] == 'O')
125 && (arg[1] == 'n' || arg[1] == 'N')))
126 return true;
127 m4_warn (context, 0, caller, _("unknown directive %s"),
128 quotearg_style_mem (locale_quoting_style, arg, len));
129 return previous;
132 /* Helper method to look up a symbol table entry given an argument.
133 Warn on behalf of ARGV if VALUE is not a text argument, or if
134 MUST_EXIST and no macro exists by the name in VALUE. Return the
135 result of the lookup, or NULL. */
136 m4_symbol *
137 m4_symbol_value_lookup (m4 *context, m4_macro_args *argv, size_t i,
138 bool must_exist)
140 m4_symbol *result = NULL;
141 if (m4_is_arg_text (argv, i))
143 const char *name = M4ARG (i);
144 size_t len = M4ARGLEN (i);
145 result = m4_symbol_lookup (M4SYMTAB, name, len);
146 if (must_exist && !result
147 && m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF))
148 m4_warn (context, 0, argv->info, _("undefined macro %s"),
149 quotearg_style_mem (locale_quoting_style, name, len));
151 else
152 m4_warn (context, 0, argv->info, _("invalid macro name ignored"));
153 return result;
156 /* Return an escaped version of the macro name corresponding to
157 CALLER, for use in error messages that do not use the m4_warn
158 machinery. This call occupies slot 0 of the quotearg
159 machinery. */
160 const char *m4_info_name (const m4_call_info *caller)
162 return quotearg_style_mem (locale_quoting_style, caller->name,
163 caller->name_len);
166 /* Helper for all error reporting. Report message based on FORMAT and
167 ARGS, on behalf of CALLER (if any), otherwise at the global
168 position in CONTEXT. If ERRNUM, decode the errno value as part of
169 the message. If STATUS, exit immediately with that status. If
170 WARN, prepend 'warning: '. */
171 static void
172 m4_verror_at_line (m4 *context, bool warn, int status, int errnum,
173 const m4_call_info *caller, const char *format,
174 va_list args)
176 char *full = NULL;
177 char *safe_macro = NULL;
178 const char *macro = caller ? caller->name : NULL;
179 size_t len = caller ? caller->name_len : 0;
180 const char *file = caller ? caller->file : m4_get_current_file (context);
181 int line = caller ? caller->line : m4_get_current_line (context);
183 assert (file || !line);
184 /* Sanitize MACRO, since we are turning around and using it in a
185 format string. The allocation is overly conservative, but
186 problematic macro names only occur via indir or changesyntax. */
187 if (macro && memchr (macro, '%', len))
189 char *p = safe_macro = xcharalloc (2 * len);
190 const char *end = macro + len;
191 while (macro != end)
193 if (*macro == '%')
195 *p++ = '%';
196 len++;
198 *p++ = *macro++;
201 if (macro)
202 /* Use slot 1, so that the rest of the code can use the simpler
203 quotearg interface in slot 0. */
204 macro = quotearg_n_mem (1, safe_macro ? safe_macro : macro, len);
205 /* Prepend warning and the macro name, as needed. But if that fails
206 for non-memory reasons (unlikely), then still use the original
207 format. */
208 if (warn && macro)
209 full = xasprintf (_("warning: %s: %s"), macro, format);
210 else if (warn)
211 full = xasprintf (_("warning: %s"), format);
212 else if (macro)
213 full = xasprintf (_("%s: %s"), macro, format);
214 verror_at_line (status, errnum, line ? file : NULL, line,
215 full ? full : format, args);
216 free (full);
217 free (safe_macro);
218 if ((!warn || m4_get_fatal_warnings_opt (context))
219 && !m4_get_exit_status (context))
220 m4_set_exit_status (context, EXIT_FAILURE);
223 /* Issue an error. The message is printf-style, based on FORMAT and
224 any other arguments, and the program name and location (if we are
225 currently parsing an input file) are automatically prepended. If
226 ERRNUM is non-zero, include strerror output in the message. If
227 CALLER, prepend the message with the macro where the message
228 occurred. If STATUS is non-zero, or if errors are fatal, call exit
229 immediately; otherwise, remember that an error occurred so that m4
230 cannot exit with success later on.*/
231 void
232 m4_error (m4 *context, int status, int errnum, const m4_call_info *caller,
233 const char *format, ...)
235 va_list args;
236 va_start (args, format);
237 if (status == EXIT_SUCCESS && m4_get_warnings_exit_opt (context))
238 status = EXIT_FAILURE;
239 m4_verror_at_line (context, false, status, errnum, caller, format, args);
240 va_end (args);
243 /* Issue a warning, if they are not being suppressed. The message is
244 printf-style, based on FORMAT and any other arguments, and the
245 program name, location (if we are currently parsing an input file),
246 and "warning:" are automatically prepended. If ERRNUM is non-zero,
247 include strerror output in the message. If CALLER, prepend the
248 message with the macro where the message occurred. If warnings are
249 fatal, call exit immediately, otherwise exit status is
250 unchanged. */
251 void
252 m4_warn (m4 *context, int errnum, const m4_call_info *caller,
253 const char *format, ...)
255 if (!m4_get_suppress_warnings_opt (context))
257 va_list args;
258 int status = EXIT_SUCCESS;
259 va_start (args, format);
260 if (m4_get_warnings_exit_opt (context))
261 status = EXIT_FAILURE;
262 m4_verror_at_line (context, true, status, errnum, caller, format, args);
263 va_end (args);
267 /* Wrap the gnulib progname module, to avoid exporting a global
268 variable from a library. Retrieve the program name for use in
269 error messages and the __program__ macro. */
270 const char *
271 m4_get_program_name (void)
273 return program_name;
276 /* Wrap the gnulib progname module, to avoid exporting a global
277 variable from a library. Set the program name for use in error
278 messages and the __program__ macro to argv[0]. */
279 void
280 m4_set_program_name (const char *name)
282 set_program_name (name);
285 /* Wrap the gnulib exitfail module, to avoid exporting a global
286 variable from a library. Set the exit status for use in gnulib
287 modules and atexit handlers. */
288 void
289 m4_set_exit_failure (int status)
291 exit_failure = status;