(root)/
m4-1.4.19/
src/
builtin.c
       1  /* GNU m4 -- A simple macro processor
       2  
       3     Copyright (C) 1989-1994, 2000, 2004, 2006-2014, 2016-2017, 2020-2021
       4     Free Software Foundation, Inc.
       5  
       6     This file is part of GNU M4.
       7  
       8     GNU M4 is free software: you can redistribute it and/or modify
       9     it under the terms of the GNU General Public License as published by
      10     the Free Software Foundation, either version 3 of the License, or
      11     (at your option) any later version.
      12  
      13     GNU M4 is distributed in the hope that it will be useful,
      14     but WITHOUT ANY WARRANTY; without even the implied warranty of
      15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16     GNU General Public License for more details.
      17  
      18     You should have received a copy of the GNU General Public License
      19     along with this program.  If not, see <https://www.gnu.org/licenses/>.
      20  */
      21  
      22  /* Code for all builtin macros, initialization of symbol table, and
      23     expansion of user defined macros.  */
      24  
      25  #include "m4.h"
      26  
      27  #include "execute.h"
      28  #include "memchr2.h"
      29  #include "progname.h"
      30  #include "regex.h"
      31  #include "spawn-pipe.h"
      32  #include "wait-process.h"
      33  
      34  #define ARG(i) (argc > (i) ? TOKEN_DATA_TEXT (argv[i]) : "")
      35  
      36  /* Initialization of builtin and predefined macros.  The table
      37     "builtin_tab" is both used for initialization, and by the "builtin"
      38     builtin.  */
      39  
      40  #define DECLARE(name) \
      41    static void name (struct obstack *, int, token_data **)
      42  
      43  DECLARE (m4___file__);
      44  DECLARE (m4___line__);
      45  DECLARE (m4___program__);
      46  DECLARE (m4_builtin);
      47  DECLARE (m4_changecom);
      48  DECLARE (m4_changequote);
      49  #ifdef ENABLE_CHANGEWORD
      50  DECLARE (m4_changeword);
      51  #endif
      52  DECLARE (m4_debugmode);
      53  DECLARE (m4_debugfile);
      54  DECLARE (m4_decr);
      55  DECLARE (m4_define);
      56  DECLARE (m4_defn);
      57  DECLARE (m4_divert);
      58  DECLARE (m4_divnum);
      59  DECLARE (m4_dnl);
      60  DECLARE (m4_dumpdef);
      61  DECLARE (m4_errprint);
      62  DECLARE (m4_esyscmd);
      63  DECLARE (m4_eval);
      64  DECLARE (m4_format);
      65  DECLARE (m4_ifdef);
      66  DECLARE (m4_ifelse);
      67  DECLARE (m4_include);
      68  DECLARE (m4_incr);
      69  DECLARE (m4_index);
      70  DECLARE (m4_indir);
      71  DECLARE (m4_len);
      72  DECLARE (m4_m4exit);
      73  DECLARE (m4_m4wrap);
      74  DECLARE (m4_maketemp);
      75  DECLARE (m4_mkstemp);
      76  DECLARE (m4_patsubst);
      77  DECLARE (m4_popdef);
      78  DECLARE (m4_pushdef);
      79  DECLARE (m4_regexp);
      80  DECLARE (m4_shift);
      81  DECLARE (m4_sinclude);
      82  DECLARE (m4_substr);
      83  DECLARE (m4_syscmd);
      84  DECLARE (m4_sysval);
      85  DECLARE (m4_traceoff);
      86  DECLARE (m4_traceon);
      87  DECLARE (m4_translit);
      88  DECLARE (m4_undefine);
      89  DECLARE (m4_undivert);
      90  
      91  #undef DECLARE
      92  
      93  static builtin const builtin_tab[] =
      94  {
      95  
      96    /* name               GNUext  macros  blind   function */
      97  
      98    { "__file__",         true,   false,  false,  m4___file__ },
      99    { "__line__",         true,   false,  false,  m4___line__ },
     100    { "__program__",      true,   false,  false,  m4___program__ },
     101    { "builtin",          true,   true,   true,   m4_builtin },
     102    { "changecom",        false,  false,  false,  m4_changecom },
     103    { "changequote",      false,  false,  false,  m4_changequote },
     104  #ifdef ENABLE_CHANGEWORD
     105    { "changeword",       true,   false,  true,   m4_changeword },
     106  #endif
     107    { "debugmode",        true,   false,  false,  m4_debugmode },
     108    { "debugfile",        true,   false,  false,  m4_debugfile },
     109    { "decr",             false,  false,  true,   m4_decr },
     110    { "define",           false,  true,   true,   m4_define },
     111    { "defn",             false,  false,  true,   m4_defn },
     112    { "divert",           false,  false,  false,  m4_divert },
     113    { "divnum",           false,  false,  false,  m4_divnum },
     114    { "dnl",              false,  false,  false,  m4_dnl },
     115    { "dumpdef",          false,  false,  false,  m4_dumpdef },
     116    { "errprint",         false,  false,  true,   m4_errprint },
     117    { "esyscmd",          true,   false,  true,   m4_esyscmd },
     118    { "eval",             false,  false,  true,   m4_eval },
     119    { "format",           true,   false,  true,   m4_format },
     120    { "ifdef",            false,  false,  true,   m4_ifdef },
     121    { "ifelse",           false,  false,  true,   m4_ifelse },
     122    { "include",          false,  false,  true,   m4_include },
     123    { "incr",             false,  false,  true,   m4_incr },
     124    { "index",            false,  false,  true,   m4_index },
     125    { "indir",            true,   true,   true,   m4_indir },
     126    { "len",              false,  false,  true,   m4_len },
     127    { "m4exit",           false,  false,  false,  m4_m4exit },
     128    { "m4wrap",           false,  false,  true,   m4_m4wrap },
     129    { "maketemp",         false,  false,  true,   m4_maketemp },
     130    { "mkstemp",          false,  false,  true,   m4_mkstemp },
     131    { "patsubst",         true,   false,  true,   m4_patsubst },
     132    { "popdef",           false,  false,  true,   m4_popdef },
     133    { "pushdef",          false,  true,   true,   m4_pushdef },
     134    { "regexp",           true,   false,  true,   m4_regexp },
     135    { "shift",            false,  false,  true,   m4_shift },
     136    { "sinclude",         false,  false,  true,   m4_sinclude },
     137    { "substr",           false,  false,  true,   m4_substr },
     138    { "syscmd",           false,  false,  true,   m4_syscmd },
     139    { "sysval",           false,  false,  false,  m4_sysval },
     140    { "traceoff",         false,  false,  false,  m4_traceoff },
     141    { "traceon",          false,  false,  false,  m4_traceon },
     142    { "translit",         false,  false,  true,   m4_translit },
     143    { "undefine",         false,  false,  true,   m4_undefine },
     144    { "undivert",         false,  false,  false,  m4_undivert },
     145  
     146    { 0,                  false,  false,  false,  0 },
     147  
     148    /* placeholder is intentionally stuck after the table end delimiter,
     149       so that we can easily find it, while not treating it as a real
     150       builtin.  */
     151    { "placeholder",      true,   false,  false,  m4_placeholder },
     152  };
     153  
     154  static predefined const predefined_tab[] =
     155  {
     156  #if UNIX
     157    { "unix",     "__unix__",     "" },
     158  #endif
     159  #if W32_NATIVE
     160    { "windows",  "__windows__",  "" },
     161  #endif
     162  #if OS2
     163    { "os2",      "__os2__",      "" },
     164  #endif
     165  #if !UNIX && !W32_NATIVE && !OS2
     166  # warning Platform macro not provided
     167  #endif
     168    { NULL,       "__gnu__",      "" },
     169  
     170    { NULL,       NULL,           NULL },
     171  };
     172  
     173  /*----------------------------------------.
     174  | Find the builtin, which lives on ADDR.  |
     175  `----------------------------------------*/
     176  
     177  const builtin * ATTRIBUTE_PURE
     178  find_builtin_by_addr (builtin_func *func)
     179  {
     180    const builtin *bp;
     181  
     182    for (bp = &builtin_tab[0]; bp->name != NULL; bp++)
     183      if (bp->func == func)
     184        return bp;
     185    if (func == m4_placeholder)
     186      return bp + 1;
     187    return NULL;
     188  }
     189  
     190  /*----------------------------------------------------------.
     191  | Find the builtin, which has NAME.  On failure, return the |
     192  | placeholder builtin.                                      |
     193  `----------------------------------------------------------*/
     194  
     195  const builtin * ATTRIBUTE_PURE
     196  find_builtin_by_name (const char *name)
     197  {
     198    const builtin *bp;
     199  
     200    for (bp = &builtin_tab[0]; bp->name != NULL; bp++)
     201      if (STREQ (bp->name, name))
     202        return bp;
     203    return bp + 1;
     204  }
     205  
     206  /*----------------------------------------------------------------.
     207  | Install a builtin macro with name NAME, bound to the C function |
     208  | given in BP.  MODE is SYMBOL_INSERT or SYMBOL_PUSHDEF.          |
     209  `----------------------------------------------------------------*/
     210  
     211  void
     212  define_builtin (const char *name, const builtin *bp, symbol_lookup mode)
     213  {
     214    symbol *sym;
     215  
     216    sym = lookup_symbol (name, mode);
     217    SYMBOL_TYPE (sym) = TOKEN_FUNC;
     218    SYMBOL_MACRO_ARGS (sym) = bp->groks_macro_args;
     219    SYMBOL_BLIND_NO_ARGS (sym) = bp->blind_if_no_args;
     220    SYMBOL_FUNC (sym) = bp->func;
     221  }
     222  
     223  /* Storage for the compiled regular expression of
     224     --warn-macro-sequence.  */
     225  static struct re_pattern_buffer macro_sequence_buf;
     226  
     227  /* Storage for the matches of --warn-macro-sequence.  */
     228  static struct re_registers macro_sequence_regs;
     229  
     230  /* True if --warn-macro-sequence is in effect.  */
     231  static bool macro_sequence_inuse;
     232  
     233  /*----------------------------------------.
     234  | Clean up regular expression variables.  |
     235  `----------------------------------------*/
     236  
     237  static void
     238  free_pattern_buffer (struct re_pattern_buffer *buf, struct re_registers *regs)
     239  {
     240    regfree (buf);
     241    free (regs->start);
     242    free (regs->end);
     243  }
     244  
     245  /*-----------------------------------------------------------------.
     246  | Set the regular expression of --warn-macro-sequence that will be |
     247  | checked during define and pushdef.  Exit on failure.             |
     248  `-----------------------------------------------------------------*/
     249  void
     250  set_macro_sequence (const char *regexp)
     251  {
     252    const char *msg;
     253  
     254    if (! regexp)
     255      regexp = DEFAULT_MACRO_SEQUENCE;
     256    else if (regexp[0] == '\0')
     257      {
     258        macro_sequence_inuse = false;
     259        return;
     260      }
     261  
     262    msg = re_compile_pattern (regexp, strlen (regexp), &macro_sequence_buf);
     263    if (msg != NULL)
     264      m4_failure (0, _("--warn-macro-sequence: bad regular expression `%s': %s"),
     265                  regexp, msg);
     266    re_set_registers (&macro_sequence_buf, &macro_sequence_regs,
     267                      macro_sequence_regs.num_regs,
     268                      macro_sequence_regs.start, macro_sequence_regs.end);
     269    macro_sequence_inuse = true;
     270  }
     271  
     272  /*-----------------------------------------------------------.
     273  | Free dynamic memory utilized by the macro sequence regular |
     274  | expression during the define builtin.                      |
     275  `-----------------------------------------------------------*/
     276  void
     277  free_macro_sequence (void)
     278  {
     279    free_pattern_buffer (&macro_sequence_buf, &macro_sequence_regs);
     280  }
     281  
     282  /*-----------------------------------------------------------------.
     283  | Define a predefined or user-defined macro, with name NAME, and   |
     284  | expansion TEXT.  MODE destinguishes between the "define" and the |
     285  | "pushdef" case.  It is also used from main.                      |
     286  `-----------------------------------------------------------------*/
     287  
     288  void
     289  define_user_macro (const char *name, const char *text, symbol_lookup mode)
     290  {
     291    symbol *s;
     292    char *defn = xstrdup (text ? text : "");
     293  
     294    s = lookup_symbol (name, mode);
     295    if (SYMBOL_TYPE (s) == TOKEN_TEXT)
     296      free (SYMBOL_TEXT (s));
     297  
     298    SYMBOL_TYPE (s) = TOKEN_TEXT;
     299    SYMBOL_TEXT (s) = defn;
     300  
     301    /* Implement --warn-macro-sequence.  */
     302    if (macro_sequence_inuse && text)
     303      {
     304        regoff_t offset = 0;
     305        size_t len = strlen (defn);
     306  
     307        while ((offset = re_search (&macro_sequence_buf, defn, len, offset,
     308                                    len - offset, &macro_sequence_regs)) >= 0)
     309          {
     310            /* Skip empty matches.  */
     311            if (macro_sequence_regs.start[0] == macro_sequence_regs.end[0])
     312              offset++;
     313            else
     314              {
     315                char tmp;
     316                offset = macro_sequence_regs.end[0];
     317                tmp = defn[offset];
     318                defn[offset] = '\0';
     319                M4ERROR ((warning_status, 0,
     320                          _("Warning: definition of `%s' contains sequence `%s'"),
     321                          name, defn + macro_sequence_regs.start[0]));
     322                defn[offset] = tmp;
     323              }
     324          }
     325        if (offset == -2)
     326          M4ERROR ((warning_status, 0,
     327                    _("error checking --warn-macro-sequence for macro `%s'"),
     328                    name));
     329      }
     330  }
     331  
     332  /*-----------------------------------------------.
     333  | Initialize all builtin and predefined macros.  |
     334  `-----------------------------------------------*/
     335  
     336  void
     337  builtin_init (void)
     338  {
     339    const builtin *bp;
     340    const predefined *pp;
     341    char *string;
     342  
     343    for (bp = &builtin_tab[0]; bp->name != NULL; bp++)
     344      if (!no_gnu_extensions || !bp->gnu_extension)
     345        {
     346          if (prefix_all_builtins)
     347            {
     348              string = (char *) xmalloc (strlen (bp->name) + 4);
     349              strcpy (string, "m4_");
     350              strcat (string, bp->name);
     351              define_builtin (string, bp, SYMBOL_INSERT);
     352              free (string);
     353            }
     354          else
     355            define_builtin (bp->name, bp, SYMBOL_INSERT);
     356        }
     357  
     358    for (pp = &predefined_tab[0]; pp->func != NULL; pp++)
     359      if (no_gnu_extensions)
     360        {
     361          if (pp->unix_name != NULL)
     362            define_user_macro (pp->unix_name, pp->func, SYMBOL_INSERT);
     363        }
     364      else
     365        {
     366          if (pp->gnu_name != NULL)
     367            define_user_macro (pp->gnu_name, pp->func, SYMBOL_INSERT);
     368        }
     369  }
     370  
     371  /*-------------------------------------------------------------------.
     372  | Give friendly warnings if a builtin macro is passed an             |
     373  | inappropriate number of arguments.  NAME is the macro name for     |
     374  | messages, ARGC is actual number of arguments, MIN is the minimum   |
     375  | number of acceptable arguments, negative if not applicable, MAX is |
     376  | the maximum number, negative if not applicable.                    |
     377  `-------------------------------------------------------------------*/
     378  
     379  static bool
     380  bad_argc (token_data *name, int argc, int min, int max)
     381  {
     382    bool isbad = false;
     383  
     384    if (min > 0 && argc < min)
     385      {
     386        if (!suppress_warnings)
     387          M4ERROR ((warning_status, 0,
     388                    _("Warning: too few arguments to builtin `%s'"),
     389                    TOKEN_DATA_TEXT (name)));
     390        isbad = true;
     391      }
     392    else if (max > 0 && argc > max && !suppress_warnings)
     393      M4ERROR ((warning_status, 0,
     394                _("Warning: excess arguments to builtin `%s' ignored"),
     395                TOKEN_DATA_TEXT (name)));
     396  
     397    return isbad;
     398  }
     399  
     400  /*-----------------------------------------------------------------.
     401  | The function numeric_arg () converts ARG to an int pointed to by |
     402  | VALUEP.  If the conversion fails, print error message for macro  |
     403  | MACRO.  Return true iff conversion succeeds.                     |
     404  `-----------------------------------------------------------------*/
     405  
     406  static bool
     407  numeric_arg (token_data *macro, const char *arg, int *valuep)
     408  {
     409    char *endp;
     410  
     411    if (*arg == '\0')
     412      {
     413        *valuep = 0;
     414        M4ERROR ((warning_status, 0,
     415                  _("empty string treated as 0 in builtin `%s'"),
     416                  TOKEN_DATA_TEXT (macro)));
     417      }
     418    else
     419      {
     420        errno = 0;
     421        *valuep = strtol (arg, &endp, 10);
     422        if (*endp != '\0')
     423          {
     424            M4ERROR ((warning_status, 0,
     425                      _("non-numeric argument to builtin `%s'"),
     426                      TOKEN_DATA_TEXT (macro)));
     427            return false;
     428          }
     429        if (c_isspace (*arg))
     430          M4ERROR ((warning_status, 0,
     431                    _("leading whitespace ignored in builtin `%s'"),
     432                    TOKEN_DATA_TEXT (macro)));
     433        else if (errno == ERANGE)
     434          M4ERROR ((warning_status, 0,
     435                    _("numeric overflow detected in builtin `%s'"),
     436                    TOKEN_DATA_TEXT (macro)));
     437      }
     438    return true;
     439  }
     440  
     441  /*------------------------------------------------------.
     442  | The function ntoa () converts VALUE to a signed ASCII |
     443  | representation in radix RADIX.                        |
     444  `------------------------------------------------------*/
     445  
     446  /* Digits for number to ASCII conversions.  */
     447  static char const digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
     448  
     449  const char *
     450  ntoa (int32_t value, int radix)
     451  {
     452    bool negative;
     453    uint32_t uvalue;
     454    static char str[256];
     455    char *s = &str[sizeof str];
     456  
     457    *--s = '\0';
     458  
     459    if (value < 0)
     460      {
     461        negative = true;
     462        uvalue = -(uint32_t) value;
     463      }
     464    else
     465      {
     466        negative = false;
     467        uvalue = (uint32_t) value;
     468      }
     469  
     470    do
     471      {
     472        *--s = digits[uvalue % radix];
     473        uvalue /= radix;
     474      }
     475    while (uvalue > 0);
     476  
     477    if (negative)
     478      *--s = '-';
     479    return s;
     480  }
     481  
     482  /*---------------------------------------------------------------.
     483  | Format an int VAL, and stuff it into an obstack OBS.  Used for |
     484  | macros expanding to numbers.                                   |
     485  `---------------------------------------------------------------*/
     486  
     487  static void
     488  shipout_int (struct obstack *obs, int val)
     489  {
     490    const char *s;
     491  
     492    s = ntoa ((int32_t) val, 10);
     493    obstack_grow (obs, s, strlen (s));
     494  }
     495  
     496  /*-------------------------------------------------------------------.
     497  | Print ARGC arguments from the table ARGV to obstack OBS, separated |
     498  | by SEP, and quoted by the current quotes if QUOTED is true.        |
     499  `-------------------------------------------------------------------*/
     500  
     501  static void
     502  dump_args (struct obstack *obs, int argc, token_data **argv,
     503             const char *sep, bool quoted)
     504  {
     505    int i;
     506    size_t len = strlen (sep);
     507  
     508    for (i = 1; i < argc; i++)
     509      {
     510        if (i > 1)
     511          obstack_grow (obs, sep, len);
     512        if (quoted)
     513          obstack_grow (obs, lquote.string, lquote.length);
     514        obstack_grow (obs, TOKEN_DATA_TEXT (argv[i]),
     515                      strlen (TOKEN_DATA_TEXT (argv[i])));
     516        if (quoted)
     517          obstack_grow (obs, rquote.string, rquote.length);
     518      }
     519  }
     520  
     521  /* The rest of this file is code for builtins and expansion of user
     522     defined macros.  All the functions for builtins have a prototype as:
     523  
     524          void m4_MACRONAME (struct obstack *obs, int argc, char *argv[]);
     525  
     526     The function are expected to leave their expansion on the obstack OBS,
     527     as an unfinished object.  ARGV is a table of ARGC pointers to the
     528     individual arguments to the macro.  Please note that in general
     529     argv[argc] != NULL.  */
     530  
     531  /* The first section are macros for definining, undefining, examining,
     532     changing, ... other macros.  */
     533  
     534  /*-------------------------------------------------------------------.
     535  | The function define_macro is common for the builtins "define",     |
     536  | "undefine", "pushdef" and "popdef".  ARGC and ARGV is as for the   |
     537  | caller, and MODE argument determines how the macro name is entered |
     538  | into the symbol table.                                             |
     539  `-------------------------------------------------------------------*/
     540  
     541  static void
     542  define_macro (int argc, token_data **argv, symbol_lookup mode)
     543  {
     544    const builtin *bp;
     545  
     546    if (bad_argc (argv[0], argc, 2, 3))
     547      return;
     548  
     549    if (TOKEN_DATA_TYPE (argv[1]) != TOKEN_TEXT)
     550      {
     551        M4ERROR ((warning_status, 0,
     552                  _("Warning: %s: invalid macro name ignored"), ARG (0)));
     553        return;
     554      }
     555  
     556    if (argc == 2)
     557      {
     558        define_user_macro (ARG (1), "", mode);
     559        return;
     560      }
     561  
     562    switch (TOKEN_DATA_TYPE (argv[2]))
     563      {
     564      case TOKEN_TEXT:
     565        define_user_macro (ARG (1), ARG (2), mode);
     566        break;
     567  
     568      case TOKEN_FUNC:
     569        bp = find_builtin_by_addr (TOKEN_DATA_FUNC (argv[2]));
     570        if (bp == NULL)
     571          return;
     572        else
     573          define_builtin (ARG (1), bp, mode);
     574        break;
     575  
     576      case TOKEN_VOID:
     577      default:
     578        M4ERROR ((warning_status, 0,
     579                  "INTERNAL ERROR: bad token data type in define_macro ()"));
     580        abort ();
     581      }
     582  }
     583  
     584  static void
     585  m4_define (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
     586  {
     587    define_macro (argc, argv, SYMBOL_INSERT);
     588  }
     589  
     590  static void
     591  m4_undefine (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
     592  {
     593    int i;
     594    if (bad_argc (argv[0], argc, 2, -1))
     595      return;
     596    for (i = 1; i < argc; i++)
     597      lookup_symbol (ARG (i), SYMBOL_DELETE);
     598  }
     599  
     600  static void
     601  m4_pushdef (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
     602  {
     603    define_macro (argc, argv,  SYMBOL_PUSHDEF);
     604  }
     605  
     606  static void
     607  m4_popdef (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
     608  {
     609    int i;
     610    if (bad_argc (argv[0], argc, 2, -1))
     611      return;
     612    for (i = 1; i < argc; i++)
     613      lookup_symbol (ARG (i), SYMBOL_POPDEF);
     614  }
     615  
     616  /*---------------------.
     617  | Conditionals of m4.  |
     618  `---------------------*/
     619  
     620  static void
     621  m4_ifdef (struct obstack *obs, int argc, token_data **argv)
     622  {
     623    symbol *s;
     624    const char *result;
     625  
     626    if (bad_argc (argv[0], argc, 3, 4))
     627      return;
     628    s = lookup_symbol (ARG (1), SYMBOL_LOOKUP);
     629  
     630    if (s != NULL && SYMBOL_TYPE (s) != TOKEN_VOID)
     631      result = ARG (2);
     632    else if (argc >= 4)
     633      result = ARG (3);
     634    else
     635      result = NULL;
     636  
     637    if (result != NULL)
     638      obstack_grow (obs, result, strlen (result));
     639  }
     640  
     641  static void
     642  m4_ifelse (struct obstack *obs, int argc, token_data **argv)
     643  {
     644    const char *result;
     645    token_data *me = argv[0];
     646  
     647    if (argc == 2)
     648      return;
     649  
     650    if (bad_argc (me, argc, 4, -1))
     651      return;
     652    else
     653      /* Diagnose excess arguments if 5, 8, 11, etc., actual arguments.  */
     654      bad_argc (me, (argc + 2) % 3, -1, 1);
     655  
     656    argv++;
     657    argc--;
     658  
     659    result = NULL;
     660    while (result == NULL)
     661  
     662      if (STREQ (ARG (0), ARG (1)))
     663        result = ARG (2);
     664  
     665      else
     666        switch (argc)
     667          {
     668          case 3:
     669            return;
     670  
     671          case 4:
     672          case 5:
     673            result = ARG (3);
     674            break;
     675  
     676          default:
     677            argc -= 3;
     678            argv += 3;
     679          }
     680  
     681    obstack_grow (obs, result, strlen (result));
     682  }
     683  
     684  /*-------------------------------------------------------------------.
     685  | The function dump_symbol () is for use by "dumpdef".  It builds up |
     686  | a table of all defined, un-shadowed, symbols.                      |
     687  `-------------------------------------------------------------------*/
     688  
     689  /* The structure dump_symbol_data is used to pass the information needed
     690     from call to call to dump_symbol.  */
     691  
     692  struct dump_symbol_data
     693  {
     694    struct obstack *obs;          /* obstack for table */
     695    symbol **base;                /* base of table */
     696    int size;                     /* size of table */
     697  };
     698  
     699  static void
     700  dump_symbol (symbol *sym, void *arg)
     701  {
     702    struct dump_symbol_data *data = (struct dump_symbol_data *) arg;
     703    if (SYMBOL_TYPE (sym) != TOKEN_VOID)
     704      {
     705        obstack_blank (data->obs, sizeof (symbol *));
     706        data->base = (symbol **) obstack_base (data->obs);
     707        data->base[data->size++] = sym;
     708      }
     709  }
     710  
     711  /*------------------------------------------------------------------------.
     712  | qsort comparison routine, for sorting the table made in m4_dumpdef ().  |
     713  `------------------------------------------------------------------------*/
     714  
     715  static int
     716  dumpdef_cmp (const void *s1, const void *s2)
     717  {
     718    return strcmp (SYMBOL_NAME (* (symbol *const *) s1),
     719                   SYMBOL_NAME (* (symbol *const *) s2));
     720  }
     721  
     722  /*-------------------------------------------------------------.
     723  | Implementation of "dumpdef" itself.  It builds up a table of |
     724  | pointers to symbols, sorts it and prints the sorted table.   |
     725  `-------------------------------------------------------------*/
     726  
     727  static void
     728  m4_dumpdef (struct obstack *obs, int argc, token_data **argv)
     729  {
     730    symbol *s;
     731    int i;
     732    struct dump_symbol_data data;
     733    const builtin *bp;
     734  
     735    data.obs = obs;
     736    data.base = (symbol **) obstack_base (obs);
     737    data.size = 0;
     738  
     739    if (argc == 1)
     740      {
     741        hack_all_symbols (dump_symbol, &data);
     742      }
     743    else
     744      {
     745        for (i = 1; i < argc; i++)
     746          {
     747            s = lookup_symbol (TOKEN_DATA_TEXT (argv[i]), SYMBOL_LOOKUP);
     748            if (s != NULL && SYMBOL_TYPE (s) != TOKEN_VOID)
     749              dump_symbol (s, &data);
     750            else
     751              M4ERROR ((warning_status, 0,
     752                        _("undefined macro `%s'"), TOKEN_DATA_TEXT (argv[i])));
     753          }
     754      }
     755  
     756    /* Make table of symbols invisible to expand_macro ().  */
     757  
     758    obstack_finish (obs);
     759  
     760    qsort (data.base, data.size, sizeof (symbol *), dumpdef_cmp);
     761  
     762    for (; data.size > 0; --data.size, data.base++)
     763      {
     764        DEBUG_PRINT1 ("%s:\t", SYMBOL_NAME (data.base[0]));
     765  
     766        switch (SYMBOL_TYPE (data.base[0]))
     767          {
     768          case TOKEN_TEXT:
     769            if (debug_level & DEBUG_TRACE_QUOTE)
     770              DEBUG_PRINT3 ("%s%s%s\n",
     771                            lquote.string, SYMBOL_TEXT (data.base[0]), rquote.string);
     772            else
     773              DEBUG_PRINT1 ("%s\n", SYMBOL_TEXT (data.base[0]));
     774            break;
     775  
     776          case TOKEN_FUNC:
     777            bp = find_builtin_by_addr (SYMBOL_FUNC (data.base[0]));
     778            if (bp == NULL)
     779              {
     780                M4ERROR ((warning_status, 0, "\
     781  INTERNAL ERROR: builtin not found in builtin table"));
     782                abort ();
     783              }
     784            DEBUG_PRINT1 ("<%s>\n", bp->name);
     785            break;
     786  
     787          case TOKEN_VOID:
     788          default:
     789            M4ERROR ((warning_status, 0,
     790                      "INTERNAL ERROR: bad token data type in m4_dumpdef ()"));
     791            abort ();
     792            break;
     793          }
     794      }
     795  }
     796  
     797  /*-----------------------------------------------------------------.
     798  | The builtin "builtin" allows calls to builtin macros, even if    |
     799  | their definition has been overridden or shadowed.  It is thus    |
     800  | possible to redefine builtins, and still access their original   |
     801  | definition.  This macro is not available in compatibility mode.  |
     802  `-----------------------------------------------------------------*/
     803  
     804  static void
     805  m4_builtin (struct obstack *obs, int argc, token_data **argv)
     806  {
     807    const builtin *bp;
     808    const char *name;
     809  
     810    if (bad_argc (argv[0], argc, 2, -1))
     811      return;
     812    if (TOKEN_DATA_TYPE (argv[1]) != TOKEN_TEXT)
     813      {
     814        M4ERROR ((warning_status, 0,
     815                  _("Warning: %s: invalid macro name ignored"), ARG (0)));
     816        return;
     817      }
     818  
     819    name = ARG (1);
     820    bp = find_builtin_by_name (name);
     821    if (bp->func == m4_placeholder)
     822      M4ERROR ((warning_status, 0,
     823                _("undefined builtin `%s'"), name));
     824    else
     825      {
     826        int i;
     827        if (! bp->groks_macro_args)
     828          for (i = 2; i < argc; i++)
     829            if (TOKEN_DATA_TYPE (argv[i]) != TOKEN_TEXT)
     830              {
     831                TOKEN_DATA_TYPE (argv[i]) = TOKEN_TEXT;
     832                TOKEN_DATA_TEXT (argv[i]) = (char *) "";
     833              }
     834        bp->func (obs, argc - 1, argv + 1);
     835      }
     836  }
     837  
     838  /*-------------------------------------------------------------------.
     839  | The builtin "indir" allows indirect calls to macros, even if their |
     840  | name is not a proper macro name.  It is thus possible to define    |
     841  | macros with ill-formed names for internal use in larger macro      |
     842  | packages.  This macro is not available in compatibility mode.      |
     843  `-------------------------------------------------------------------*/
     844  
     845  static void
     846  m4_indir (struct obstack *obs, int argc, token_data **argv)
     847  {
     848    symbol *s;
     849    const char *name;
     850  
     851    if (bad_argc (argv[0], argc, 2, -1))
     852      return;
     853    if (TOKEN_DATA_TYPE (argv[1]) != TOKEN_TEXT)
     854      {
     855        M4ERROR ((warning_status, 0,
     856                  _("Warning: %s: invalid macro name ignored"), ARG (0)));
     857        return;
     858      }
     859  
     860    name = ARG (1);
     861    s = lookup_symbol (name, SYMBOL_LOOKUP);
     862    if (s == NULL || SYMBOL_TYPE (s) == TOKEN_VOID)
     863      M4ERROR ((warning_status, 0,
     864                _("undefined macro `%s'"), name));
     865    else
     866      {
     867        int i;
     868        if (! SYMBOL_MACRO_ARGS (s))
     869          for (i = 2; i < argc; i++)
     870            if (TOKEN_DATA_TYPE (argv[i]) != TOKEN_TEXT)
     871              {
     872                TOKEN_DATA_TYPE (argv[i]) = TOKEN_TEXT;
     873                TOKEN_DATA_TEXT (argv[i]) = (char *) "";
     874              }
     875        call_macro (s, argc - 1, argv + 1, obs);
     876      }
     877  }
     878  
     879  /*------------------------------------------------------------------.
     880  | The macro "defn" returns the quoted definition of the macro named |
     881  | by the first argument.  If the macro is builtin, it will push a   |
     882  | special macro-definition token on the input stack.                |
     883  `------------------------------------------------------------------*/
     884  
     885  static void
     886  m4_defn (struct obstack *obs, int argc, token_data **argv)
     887  {
     888    symbol *s;
     889    builtin_func *b;
     890    unsigned int i;
     891  
     892    if (bad_argc (argv[0], argc, 2, -1))
     893      return;
     894  
     895    assert (0 < argc);
     896    for (i = 1; i < (unsigned) argc; i++)
     897      {
     898        const char *arg = ARG((int) i);
     899        s = lookup_symbol (arg, SYMBOL_LOOKUP);
     900        if (s == NULL)
     901          continue;
     902  
     903        switch (SYMBOL_TYPE (s))
     904          {
     905          case TOKEN_TEXT:
     906            obstack_grow (obs, lquote.string, lquote.length);
     907            obstack_grow (obs, SYMBOL_TEXT (s), strlen (SYMBOL_TEXT (s)));
     908            obstack_grow (obs, rquote.string, rquote.length);
     909            break;
     910  
     911          case TOKEN_FUNC:
     912            b = SYMBOL_FUNC (s);
     913            if (b == m4_placeholder)
     914              M4ERROR ((warning_status, 0, _("\
     915  builtin `%s' requested by frozen file is not supported"), arg));
     916            else if (argc != 2)
     917              M4ERROR ((warning_status, 0,
     918                        _("Warning: cannot concatenate builtin `%s'"),
     919                        arg));
     920            else
     921              push_macro (b);
     922            break;
     923  
     924          case TOKEN_VOID:
     925            /* Nothing to do for traced but undefined macro.  */
     926            break;
     927  
     928          default:
     929            M4ERROR ((warning_status, 0,
     930                      "INTERNAL ERROR: bad symbol type in m4_defn ()"));
     931            abort ();
     932          }
     933      }
     934  }
     935  
     936  /*--------------------------------------------------------------.
     937  | This section contains macros to handle the builtins "syscmd", |
     938  | "esyscmd" and "sysval".  "esyscmd" is GNU specific.           |
     939  `--------------------------------------------------------------*/
     940  
     941  /* Exit code from last "syscmd" command.  */
     942  static int sysval;
     943  
     944  static void
     945  m4_syscmd (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
     946  {
     947    const char *cmd = ARG (1);
     948    int status;
     949    int sig_status;
     950    const char *prog_args[4] = { "sh", "-c" };
     951    if (bad_argc (argv[0], argc, 2, 2) || !*cmd)
     952      {
     953        /* The empty command is successful.  */
     954        sysval = 0;
     955        return;
     956      }
     957  
     958    debug_flush_files ();
     959  #if W32_NATIVE
     960    if (strstr (SYSCMD_SHELL, "cmd"))
     961      {
     962        prog_args[0] = "cmd";
     963        prog_args[1] = "/c";
     964      }
     965  #endif
     966    prog_args[2] = cmd;
     967    errno = 0;
     968    status = execute (ARG (0), SYSCMD_SHELL, prog_args, NULL, false,
     969                      false, false, false, true, false, &sig_status);
     970    if (sig_status)
     971      {
     972        assert (status == 127);
     973        sysval = sig_status << 8;
     974      }
     975    else
     976      {
     977        if (status == 127 && errno)
     978          M4ERROR ((warning_status, errno, _("cannot run command `%s'"), cmd));
     979        sysval = status;
     980      }
     981  }
     982  
     983  static void
     984  m4_esyscmd (struct obstack *obs, int argc, token_data **argv)
     985  {
     986    const char *cmd = ARG (1);
     987    const char *prog_args[4] = { "sh", "-c" };
     988    pid_t child;
     989    int fd;
     990    FILE *pin;
     991    int status;
     992    int sig_status;
     993  
     994    if (bad_argc (argv[0], argc, 2, 2) || !*cmd)
     995      {
     996        /* The empty command is successful.  */
     997        sysval = 0;
     998        return;
     999      }
    1000  
    1001    debug_flush_files ();
    1002  #if W32_NATIVE
    1003    if (strstr (SYSCMD_SHELL, "cmd"))
    1004      {
    1005        prog_args[0] = "cmd";
    1006        prog_args[1] = "/c";
    1007      }
    1008  #endif
    1009    prog_args[2] = cmd;
    1010    errno = 0;
    1011    child = create_pipe_in (ARG (0), SYSCMD_SHELL, prog_args, NULL,
    1012                            NULL, false, true, false, &fd);
    1013    if (child == -1)
    1014      {
    1015        M4ERROR ((warning_status, errno, _("cannot run command `%s'"), cmd));
    1016        sysval = 127;
    1017        return;
    1018      }
    1019  #if OS2
    1020    /* On OS/2 kLIBC, fdopen() creates a stream in a mode of a file descriptor.
    1021       So include "t" to open a stream in a text mode explicitly on OS/2. */
    1022    pin = fdopen (fd, "rt");
    1023  #else
    1024    pin = fdopen (fd, "r");
    1025  #endif
    1026    if (pin == NULL)
    1027      {
    1028        M4ERROR ((warning_status, errno, _("cannot run command `%s'"), cmd));
    1029        sysval = 127;
    1030        close (fd);
    1031        return;
    1032      }
    1033    while (1)
    1034      {
    1035        size_t avail = obstack_room (obs);
    1036        size_t len;
    1037        if (!avail)
    1038          {
    1039            int ch = getc (pin);
    1040            if (ch == EOF)
    1041              break;
    1042            obstack_1grow (obs, ch);
    1043            continue;
    1044          }
    1045        len = fread (obstack_next_free (obs), 1, avail, pin);
    1046        if (len <= 0)
    1047          break;
    1048        obstack_blank_fast (obs, len);
    1049      }
    1050    if (ferror (pin) || fclose (pin))
    1051      m4_failure (errno, _("cannot read pipe"));
    1052    errno = 0;
    1053    status = wait_subprocess (child, ARG (0), false, true, true, false,
    1054                              &sig_status);
    1055    if (sig_status)
    1056      {
    1057        assert (status == 127);
    1058        sysval = sig_status << 8;
    1059      }
    1060    else
    1061      {
    1062        if (status == 127 && errno)
    1063          M4ERROR ((warning_status, errno, _("cannot run command `%s'"), cmd));
    1064        sysval = status;
    1065      }
    1066  }
    1067  
    1068  static void
    1069  m4_sysval (struct obstack *obs, int argc MAYBE_UNUSED,
    1070             token_data **argv MAYBE_UNUSED)
    1071  {
    1072    shipout_int (obs, sysval);
    1073  }
    1074  
    1075  /*------------------------------------------------------------------.
    1076  | This section contains the top level code for the "eval" builtin.  |
    1077  | The actual work is done in the function evaluate (), which lives  |
    1078  | in eval.c.                                                        |
    1079  `------------------------------------------------------------------*/
    1080  
    1081  static void
    1082  m4_eval (struct obstack *obs, int argc, token_data **argv)
    1083  {
    1084    int32_t value = 0;
    1085    int radix = 10;
    1086    int min = 1;
    1087    const char *s;
    1088  
    1089    if (bad_argc (argv[0], argc, 2, 4))
    1090      return;
    1091  
    1092    if (*ARG (2) && !numeric_arg (argv[0], ARG (2), &radix))
    1093      return;
    1094  
    1095    if (radix < 1 || radix > (int) strlen (digits))
    1096      {
    1097        M4ERROR ((warning_status, 0,
    1098                  _("radix %d in builtin `%s' out of range"),
    1099                  radix, ARG (0)));
    1100        return;
    1101      }
    1102  
    1103    if (argc >= 4 && !numeric_arg (argv[0], ARG (3), &min))
    1104      return;
    1105    if (min < 0)
    1106      {
    1107        M4ERROR ((warning_status, 0,
    1108                  _("negative width to builtin `%s'"), ARG (0)));
    1109        return;
    1110      }
    1111  
    1112    if (!*ARG (1))
    1113      M4ERROR ((warning_status, 0,
    1114                _("empty string treated as 0 in builtin `%s'"), ARG (0)));
    1115    else if (evaluate (ARG (1), &value))
    1116      return;
    1117  
    1118    if (radix == 1)
    1119      {
    1120        if (value < 0)
    1121          {
    1122            obstack_1grow (obs, '-');
    1123            value = -value;
    1124          }
    1125        /* This assumes 2's-complement for correctly handling INT_MIN.  */
    1126        while (min-- - value > 0)
    1127          obstack_1grow (obs, '0');
    1128        while (value-- != 0)
    1129          obstack_1grow (obs, '1');
    1130        obstack_1grow (obs, '\0');
    1131        return;
    1132      }
    1133  
    1134    s = ntoa (value, radix);
    1135  
    1136    if (*s == '-')
    1137      {
    1138        obstack_1grow (obs, '-');
    1139        s++;
    1140      }
    1141    for (min -= strlen (s); --min >= 0;)
    1142      obstack_1grow (obs, '0');
    1143  
    1144    obstack_grow (obs, s, strlen (s));
    1145  }
    1146  
    1147  static void
    1148  m4_incr (struct obstack *obs, int argc, token_data **argv)
    1149  {
    1150    int value;
    1151  
    1152    if (bad_argc (argv[0], argc, 2, 2))
    1153      return;
    1154  
    1155    if (!numeric_arg (argv[0], ARG (1), &value))
    1156      return;
    1157  
    1158    /* Minimize undefined C behavior on overflow.  This code assumes
    1159       that the implementation-defined overflow when casting unsigned to
    1160       signed is a silent twos-complement wrap-around.  */
    1161    uint32_t v = value;
    1162    int32_t w = v + 1;
    1163    shipout_int (obs, w);
    1164  }
    1165  
    1166  static void
    1167  m4_decr (struct obstack *obs, int argc, token_data **argv)
    1168  {
    1169    int value;
    1170  
    1171    if (bad_argc (argv[0], argc, 2, 2))
    1172      return;
    1173  
    1174    if (!numeric_arg (argv[0], ARG (1), &value))
    1175      return;
    1176  
    1177    /* Minimize undefined C behavior on overflow.  This code assumes
    1178       that the implementation-defined overflow when casting unsigned to
    1179       signed is a silent twos-complement wrap-around.  */
    1180    uint32_t v = value;
    1181    int32_t w = v - 1;
    1182    shipout_int (obs, w);
    1183  }
    1184  
    1185  /* This section contains the macros "divert", "undivert" and "divnum" for
    1186     handling diversion.  The utility functions used lives in output.c.  */
    1187  
    1188  /*-----------------------------------------------------------------.
    1189  | Divert further output to the diversion given by ARGV[1].  Out of |
    1190  | range means discard further output.                              |
    1191  `-----------------------------------------------------------------*/
    1192  
    1193  static void
    1194  m4_divert (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
    1195  {
    1196    int i = 0;
    1197  
    1198    if (bad_argc (argv[0], argc, 1, 2))
    1199      return;
    1200  
    1201    if (argc >= 2 && !numeric_arg (argv[0], ARG (1), &i))
    1202      return;
    1203  
    1204    make_diversion (i);
    1205  }
    1206  
    1207  /*-----------------------------------------------------.
    1208  | Expand to the current diversion number, -1 if none.  |
    1209  `-----------------------------------------------------*/
    1210  
    1211  static void
    1212  m4_divnum (struct obstack *obs, int argc, token_data **argv)
    1213  {
    1214    if (bad_argc (argv[0], argc, 1, 1))
    1215      return;
    1216    shipout_int (obs, current_diversion);
    1217  }
    1218  
    1219  /*------------------------------------------------------------------.
    1220  | Bring back the diversion given by the argument list.  If none is  |
    1221  | specified, bring back all diversions.  GNU specific is the option |
    1222  | of undiverting named files, by passing a non-numeric argument to  |
    1223  | undivert ().                                                      |
    1224  `------------------------------------------------------------------*/
    1225  
    1226  static void
    1227  m4_undivert (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
    1228  {
    1229    int i, file;
    1230    FILE *fp;
    1231    char *endp;
    1232  
    1233    if (argc == 1)
    1234      undivert_all ();
    1235    else
    1236      for (i = 1; i < argc; i++)
    1237        {
    1238          file = strtol (ARG (i), &endp, 10);
    1239          if (*endp == '\0' && !c_isspace (*ARG (i)))
    1240            insert_diversion (file);
    1241          else if (no_gnu_extensions)
    1242            M4ERROR ((warning_status, 0,
    1243                      _("non-numeric argument to builtin `%s'"), ARG (0)));
    1244          else
    1245            {
    1246              fp = m4_path_search (ARG (i), NULL);
    1247              if (fp != NULL)
    1248                {
    1249                  insert_file (fp);
    1250                  if (fclose (fp) == EOF)
    1251                    M4ERROR ((warning_status, errno,
    1252                              _("error undiverting `%s'"), ARG (i)));
    1253                }
    1254              else
    1255                M4ERROR ((warning_status, errno,
    1256                          _("cannot undivert `%s'"), ARG (i)));
    1257            }
    1258        }
    1259  }
    1260  
    1261  /* This section contains various macros, which does not fall into any
    1262     specific group.  These are "dnl", "shift", "changequote", "changecom"
    1263     and "changeword".  */
    1264  
    1265  /*-----------------------------------------------------------.
    1266  | Delete all subsequent whitespace from input.  The function |
    1267  | skip_line () lives in input.c.                             |
    1268  `-----------------------------------------------------------*/
    1269  
    1270  static void
    1271  m4_dnl (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
    1272  {
    1273    if (bad_argc (argv[0], argc, 1, 1))
    1274      return;
    1275  
    1276    skip_line ();
    1277  }
    1278  
    1279  /*--------------------------------------------------------------------.
    1280  | Shift all arguments one to the left, discarding the first           |
    1281  | argument.  Each output argument is quoted with the current quotes.  |
    1282  `--------------------------------------------------------------------*/
    1283  
    1284  static void
    1285  m4_shift (struct obstack *obs, int argc, token_data **argv)
    1286  {
    1287    if (bad_argc (argv[0], argc, 2, -1))
    1288      return;
    1289    dump_args (obs, argc - 1, argv + 1, ",", true);
    1290  }
    1291  
    1292  /*--------------------------------------------------------------------------.
    1293  | Change the current quotes.  The function set_quotes () lives in input.c.  |
    1294  `--------------------------------------------------------------------------*/
    1295  
    1296  static void
    1297  m4_changequote (struct obstack *obs MAYBE_UNUSED, int argc,
    1298                  token_data **argv)
    1299  {
    1300    if (bad_argc (argv[0], argc, 1, 3))
    1301      return;
    1302  
    1303    /* Explicit NULL distinguishes between empty and missing argument.  */
    1304    set_quotes ((argc >= 2) ? TOKEN_DATA_TEXT (argv[1]) : NULL,
    1305               (argc >= 3) ? TOKEN_DATA_TEXT (argv[2]) : NULL);
    1306  }
    1307  
    1308  /*-----------------------------------------------------------------.
    1309  | Change the current comment delimiters.  The function set_comment |
    1310  | () lives in input.c.                                             |
    1311  `-----------------------------------------------------------------*/
    1312  
    1313  static void
    1314  m4_changecom (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
    1315  {
    1316    if (bad_argc (argv[0], argc, 1, 3))
    1317      return;
    1318  
    1319    /* Explicit NULL distinguishes between empty and missing argument.  */
    1320    set_comment ((argc >= 2) ? TOKEN_DATA_TEXT (argv[1]) : NULL,
    1321                 (argc >= 3) ? TOKEN_DATA_TEXT (argv[2]) : NULL);
    1322  }
    1323  
    1324  #ifdef ENABLE_CHANGEWORD
    1325  
    1326  /*---------------------------------------------------------------.
    1327  | Change the regular expression used for breaking the input into |
    1328  | words.  The function set_word_regexp () lives in input.c.      |
    1329  `---------------------------------------------------------------*/
    1330  
    1331  static void
    1332  m4_changeword (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
    1333  {
    1334    if (bad_argc (argv[0], argc, 2, 2))
    1335      return;
    1336  
    1337    set_word_regexp (TOKEN_DATA_TEXT (argv[1]));
    1338  }
    1339  
    1340  #endif /* ENABLE_CHANGEWORD */
    1341  
    1342  /* This section contains macros for inclusion of other files -- "include"
    1343     and "sinclude".  This differs from bringing back diversions, in that
    1344     the input is scanned before being copied to the output.  */
    1345  
    1346  /*---------------------------------------------------------------.
    1347  | Generic include function.  Include the file given by the first |
    1348  | argument, if it exists.  Complain about inaccessible files iff |
    1349  | SILENT is false.                                               |
    1350  `---------------------------------------------------------------*/
    1351  
    1352  static void
    1353  include (int argc, token_data **argv, bool silent)
    1354  {
    1355    FILE *fp;
    1356    char *name;
    1357  
    1358    if (bad_argc (argv[0], argc, 2, 2))
    1359      return;
    1360  
    1361    fp = m4_path_search (ARG (1), &name);
    1362    if (fp == NULL)
    1363      {
    1364        if (!silent)
    1365          {
    1366            M4ERROR ((warning_status, errno, _("cannot open `%s'"), ARG (1)));
    1367            retcode = EXIT_FAILURE;
    1368          }
    1369        return;
    1370      }
    1371  
    1372    push_file (fp, name, true);
    1373    free (name);
    1374  }
    1375  
    1376  /*------------------------------------------------.
    1377  | Include a file, complaining in case of errors.  |
    1378  `------------------------------------------------*/
    1379  
    1380  static void
    1381  m4_include (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
    1382  {
    1383    include (argc, argv, false);
    1384  }
    1385  
    1386  /*----------------------------------.
    1387  | Include a file, ignoring errors.  |
    1388  `----------------------------------*/
    1389  
    1390  static void
    1391  m4_sinclude (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
    1392  {
    1393    include (argc, argv, true);
    1394  }
    1395  
    1396  /* More miscellaneous builtins -- "maketemp", "errprint", "__file__",
    1397     "__line__", and "__program__".  The last three are GNU specific.  */
    1398  
    1399  /*------------------------------------------------------------------.
    1400  | Use the first argument as at template for a temporary file name.  |
    1401  `------------------------------------------------------------------*/
    1402  
    1403  /* Add trailing 'X' to PATTERN of length LEN as necessary, then
    1404     securely create the file, and place the quoted new file name on
    1405     OBS.  Report errors on behalf of ME.  */
    1406  static void
    1407  mkstemp_helper (struct obstack *obs, const char *me, const char *pattern,
    1408                  size_t len)
    1409  {
    1410    int fd;
    1411    size_t i;
    1412    char *name;
    1413  
    1414    /* Guarantee that there are six trailing 'X' characters, even if the
    1415       user forgot to supply them.  Output must be quoted if
    1416       successful.  */
    1417    obstack_grow (obs, lquote.string, lquote.length);
    1418    obstack_grow (obs, pattern, len);
    1419    for (i = 0; len > 0 && i < 6; i++)
    1420      if (pattern[len - i - 1] != 'X')
    1421        break;
    1422    obstack_grow0 (obs, "XXXXXX", 6 - i);
    1423    name = (char *) obstack_base (obs) + lquote.length;
    1424  
    1425    errno = 0;
    1426    fd = mkstemp (name);
    1427    if (fd < 0)
    1428      {
    1429        M4ERROR ((0, errno, _("%s: cannot create tempfile `%s'"), me, pattern));
    1430        obstack_free (obs, obstack_finish (obs));
    1431      }
    1432    else
    1433      {
    1434        close (fd);
    1435        /* Remove NUL, then finish quote.  */
    1436        obstack_blank_fast (obs, -1);
    1437        obstack_grow (obs, rquote.string, rquote.length);
    1438      }
    1439  }
    1440  
    1441  static void
    1442  m4_maketemp (struct obstack *obs, int argc, token_data **argv)
    1443  {
    1444    if (bad_argc (argv[0], argc, 2, 2))
    1445      return;
    1446    if (no_gnu_extensions)
    1447      {
    1448        /* POSIX states "any trailing 'X' characters [are] replaced with
    1449           the current process ID as a string", without referencing the
    1450           file system.  Horribly insecure, but we have to do it when we
    1451           are in traditional mode.
    1452  
    1453           For reference, Solaris m4 does:
    1454             maketemp() -> `'
    1455             maketemp(X) -> `X'
    1456             maketemp(XX) -> `Xn', where n is last digit of pid
    1457             maketemp(XXXXXXXX) -> `X00nnnnn', where nnnnn is 16-bit pid
    1458        */
    1459        const char *str = ARG (1);
    1460        int len = strlen (str);
    1461        int i;
    1462        int len2;
    1463  
    1464        M4ERROR ((warning_status, 0, _("recommend using mkstemp instead")));
    1465        for (i = len; i > 1; i--)
    1466          if (str[i - 1] != 'X')
    1467            break;
    1468        obstack_grow (obs, str, i);
    1469        str = ntoa ((int32_t) getpid (), 10);
    1470        len2 = strlen (str);
    1471        if (len2 > len - i)
    1472          obstack_grow0 (obs, str + len2 - (len - i), len - i);
    1473        else
    1474          {
    1475            while (i++ < len - len2)
    1476              obstack_1grow (obs, '0');
    1477            obstack_grow0 (obs, str, len2);
    1478          }
    1479      }
    1480    else
    1481      mkstemp_helper (obs, ARG (0), ARG (1), strlen (ARG (1)));
    1482  }
    1483  
    1484  static void
    1485  m4_mkstemp (struct obstack *obs, int argc, token_data **argv)
    1486  {
    1487    if (bad_argc (argv[0], argc, 2, 2))
    1488      return;
    1489    mkstemp_helper (obs, ARG (0), ARG (1), strlen (ARG (1)));
    1490  }
    1491  
    1492  /*----------------------------------------.
    1493  | Print all arguments on standard error.  |
    1494  `----------------------------------------*/
    1495  
    1496  static void
    1497  m4_errprint (struct obstack *obs, int argc, token_data **argv)
    1498  {
    1499    if (bad_argc (argv[0], argc, 2, -1))
    1500      return;
    1501    dump_args (obs, argc, argv, " ", false);
    1502    obstack_1grow (obs, '\0');
    1503    debug_flush_files ();
    1504    xfprintf (stderr, "%s", (char *) obstack_finish (obs));
    1505    fflush (stderr);
    1506  }
    1507  
    1508  static void
    1509  m4___file__ (struct obstack *obs, int argc, token_data **argv)
    1510  {
    1511    if (bad_argc (argv[0], argc, 1, 1))
    1512      return;
    1513    obstack_grow (obs, lquote.string, lquote.length);
    1514    obstack_grow (obs, current_file, strlen (current_file));
    1515    obstack_grow (obs, rquote.string, rquote.length);
    1516  }
    1517  
    1518  static void
    1519  m4___line__ (struct obstack *obs, int argc, token_data **argv)
    1520  {
    1521    if (bad_argc (argv[0], argc, 1, 1))
    1522      return;
    1523    shipout_int (obs, current_line);
    1524  }
    1525  
    1526  static void
    1527  m4___program__ (struct obstack *obs, int argc, token_data **argv)
    1528  {
    1529    if (bad_argc (argv[0], argc, 1, 1))
    1530      return;
    1531    obstack_grow (obs, lquote.string, lquote.length);
    1532    obstack_grow (obs, program_name, strlen (program_name));
    1533    obstack_grow (obs, rquote.string, rquote.length);
    1534  }
    1535  
    1536  /* This section contains various macros for exiting, saving input until
    1537     EOF is seen, and tracing macro calls.  That is: "m4exit", "m4wrap",
    1538     "traceon" and "traceoff".  */
    1539  
    1540  /*----------------------------------------------------------.
    1541  | Exit immediately, with exit status specified by the first |
    1542  | argument, or 0 if no arguments are present.               |
    1543  `----------------------------------------------------------*/
    1544  
    1545  static void
    1546  m4_m4exit (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
    1547  {
    1548    int exit_code = EXIT_SUCCESS;
    1549  
    1550    /* Warn on bad arguments, but still exit.  */
    1551    bad_argc (argv[0], argc, 1, 2);
    1552    if (argc >= 2 && !numeric_arg (argv[0], ARG (1), &exit_code))
    1553      exit_code = EXIT_FAILURE;
    1554    if (exit_code < 0 || exit_code > 255)
    1555      {
    1556        M4ERROR ((warning_status, 0,
    1557                  _("exit status out of range: `%d'"), exit_code));
    1558        exit_code = EXIT_FAILURE;
    1559      }
    1560    /* Change debug stream back to stderr, to force flushing debug stream and
    1561       detect any errors it might have encountered.  */
    1562    debug_set_output (NULL);
    1563    debug_flush_files ();
    1564    if (exit_code == EXIT_SUCCESS && retcode != EXIT_SUCCESS)
    1565      exit_code = retcode;
    1566    /* Propagate non-zero status to atexit handlers.  */
    1567    if (exit_code != EXIT_SUCCESS)
    1568      exit_failure = exit_code;
    1569    exit (exit_code);
    1570  }
    1571  
    1572  /*------------------------------------------------------------------.
    1573  | Save the argument text until EOF has been seen, allowing for user |
    1574  | specified cleanup action.  GNU version saves all arguments, the   |
    1575  | standard version only the first.                                  |
    1576  `------------------------------------------------------------------*/
    1577  
    1578  static void
    1579  m4_m4wrap (struct obstack *obs, int argc, token_data **argv)
    1580  {
    1581    if (bad_argc (argv[0], argc, 2, -1))
    1582      return;
    1583    if (no_gnu_extensions)
    1584      obstack_grow (obs, ARG (1), strlen (ARG (1)));
    1585    else
    1586      dump_args (obs, argc, argv, " ", false);
    1587    obstack_1grow (obs, '\0');
    1588    push_wrapup ((char *) obstack_finish (obs));
    1589  }
    1590  
    1591  /* Enable tracing of all specified macros, or all, if none is specified.
    1592     Tracing is disabled by default, when a macro is defined.  This can be
    1593     overridden by the "t" debug flag.  */
    1594  
    1595  /*------------------------------------------------------------------.
    1596  | Set_trace () is used by "traceon" and "traceoff" to enable and    |
    1597  | disable tracing of a macro.  It disables tracing if DATA is NULL, |
    1598  | otherwise it enables tracing.                                     |
    1599  `------------------------------------------------------------------*/
    1600  
    1601  static void
    1602  set_trace (symbol *sym, void *data)
    1603  {
    1604    SYMBOL_TRACED (sym) = data != NULL;
    1605    /* Remove placeholder from table if macro is undefined and untraced.  */
    1606    if (SYMBOL_TYPE (sym) == TOKEN_VOID && data == NULL)
    1607      lookup_symbol (SYMBOL_NAME (sym), SYMBOL_POPDEF);
    1608  }
    1609  
    1610  static void
    1611  m4_traceon (struct obstack *obs, int argc, token_data **argv)
    1612  {
    1613    symbol *s;
    1614    int i;
    1615  
    1616    if (argc == 1)
    1617      hack_all_symbols (set_trace, obs);
    1618    else
    1619      for (i = 1; i < argc; i++)
    1620        {
    1621          s = lookup_symbol (ARG (i), SYMBOL_LOOKUP);
    1622          if (!s)
    1623            s = lookup_symbol (ARG (i), SYMBOL_INSERT);
    1624          set_trace (s, obs);
    1625        }
    1626  }
    1627  
    1628  /*------------------------------------------------------------------------.
    1629  | Disable tracing of all specified macros, or all, if none is specified.  |
    1630  `------------------------------------------------------------------------*/
    1631  
    1632  static void
    1633  m4_traceoff (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
    1634  {
    1635    symbol *s;
    1636    int i;
    1637  
    1638    if (argc == 1)
    1639      hack_all_symbols (set_trace, NULL);
    1640    else
    1641      for (i = 1; i < argc; i++)
    1642        {
    1643          s = lookup_symbol (TOKEN_DATA_TEXT (argv[i]), SYMBOL_LOOKUP);
    1644          if (s != NULL)
    1645            set_trace (s, NULL);
    1646        }
    1647  }
    1648  
    1649  /*------------------------------------------------------------------.
    1650  | On-the-fly control of the format of the tracing output.  It takes |
    1651  | one argument, which is a character string like given to the -d    |
    1652  | option, or none in which case the debug_level is zeroed.          |
    1653  `------------------------------------------------------------------*/
    1654  
    1655  static void
    1656  m4_debugmode (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
    1657  {
    1658    int new_debug_level;
    1659    int change_flag;
    1660  
    1661    if (bad_argc (argv[0], argc, 1, 2))
    1662      return;
    1663  
    1664    if (argc == 1)
    1665      debug_level = 0;
    1666    else
    1667      {
    1668        if (ARG (1)[0] == '+' || ARG (1)[0] == '-')
    1669          {
    1670            change_flag = ARG (1)[0];
    1671            new_debug_level = debug_decode (ARG (1) + 1);
    1672          }
    1673        else
    1674          {
    1675            change_flag = 0;
    1676            new_debug_level = debug_decode (ARG (1));
    1677          }
    1678  
    1679        if (new_debug_level < 0)
    1680          M4ERROR ((warning_status, 0,
    1681                    _("Debugmode: bad debug flags: `%s'"), ARG (1)));
    1682        else
    1683          {
    1684            switch (change_flag)
    1685              {
    1686              case 0:
    1687                debug_level = new_debug_level;
    1688                break;
    1689  
    1690              case '+':
    1691                debug_level |= new_debug_level;
    1692                break;
    1693  
    1694              case '-':
    1695                debug_level &= ~new_debug_level;
    1696                break;
    1697  
    1698              default:
    1699                M4ERROR ((warning_status, 0,
    1700                          "INTERNAL ERROR: bad flag in m4_debugmode ()"));
    1701                abort ();
    1702              }
    1703          }
    1704      }
    1705  }
    1706  
    1707  /*-------------------------------------------------------------------------.
    1708  | Specify the destination of the debugging output.  With one argument, the |
    1709  | argument is taken as a file name, with no arguments, revert to stderr.   |
    1710  `-------------------------------------------------------------------------*/
    1711  
    1712  static void
    1713  m4_debugfile (struct obstack *obs MAYBE_UNUSED, int argc, token_data **argv)
    1714  {
    1715    if (bad_argc (argv[0], argc, 1, 2))
    1716      return;
    1717  
    1718    if (argc == 1)
    1719      debug_set_output (NULL);
    1720    else if (!debug_set_output (ARG (1)))
    1721      M4ERROR ((warning_status, errno,
    1722                _("cannot set debug file `%s'"), ARG (1)));
    1723  }
    1724  
    1725  /* This section contains text processing macros: "len", "index",
    1726     "substr", "translit", "format", "regexp" and "patsubst".  The last
    1727     three are GNU specific.  */
    1728  
    1729  /*---------------------------------------------.
    1730  | Expand to the length of the first argument.  |
    1731  `---------------------------------------------*/
    1732  
    1733  static void
    1734  m4_len (struct obstack *obs, int argc, token_data **argv)
    1735  {
    1736    if (bad_argc (argv[0], argc, 2, 2))
    1737      return;
    1738    shipout_int (obs, strlen (ARG (1)));
    1739  }
    1740  
    1741  /*-------------------------------------------------------------------.
    1742  | The macro expands to the first index of the second argument in the |
    1743  | first argument.                                                    |
    1744  `-------------------------------------------------------------------*/
    1745  
    1746  static void
    1747  m4_index (struct obstack *obs, int argc, token_data **argv)
    1748  {
    1749    const char *haystack;
    1750    const char *result;
    1751    int retval;
    1752  
    1753    if (bad_argc (argv[0], argc, 3, 3))
    1754      {
    1755        /* builtin(`index') is blank, but index(`abc') is 0.  */
    1756        if (argc == 2)
    1757          shipout_int (obs, 0);
    1758        return;
    1759      }
    1760  
    1761    haystack = ARG (1);
    1762    result = strstr (haystack, ARG (2));
    1763    retval = result ? result - haystack : -1;
    1764  
    1765    shipout_int (obs, retval);
    1766  }
    1767  
    1768  /*-----------------------------------------------------------------.
    1769  | The macro "substr" extracts substrings from the first argument,  |
    1770  | starting from the index given by the second argument, extending  |
    1771  | for a length given by the third argument.  If the third argument |
    1772  | is missing, the substring extends to the end of the first        |
    1773  | argument.                                                        |
    1774  `-----------------------------------------------------------------*/
    1775  
    1776  static void
    1777  m4_substr (struct obstack *obs, int argc, token_data **argv)
    1778  {
    1779    int start = 0;
    1780    int length, avail;
    1781  
    1782    if (bad_argc (argv[0], argc, 3, 4))
    1783      {
    1784        /* builtin(`substr') is blank, but substr(`abc') is abc.  */
    1785        if (argc == 2)
    1786          obstack_grow (obs, ARG (1), strlen (ARG (1)));
    1787        return;
    1788      }
    1789  
    1790    length = avail = strlen (ARG (1));
    1791    if (!numeric_arg (argv[0], ARG (2), &start))
    1792      return;
    1793  
    1794    if (argc >= 4 && !numeric_arg (argv[0], ARG (3), &length))
    1795      return;
    1796  
    1797    if (start < 0 || length <= 0 || start >= avail)
    1798      return;
    1799  
    1800    if (start + length > avail)
    1801      length = avail - start;
    1802    obstack_grow (obs, ARG (1) + start, length);
    1803  }
    1804  
    1805  /*------------------------------------------------------------------.
    1806  | For "translit", ranges are allowed in the second and third        |
    1807  | argument.  They are expanded in the following function, and the   |
    1808  | expanded strings, without any ranges left, are used to translate  |
    1809  | the characters of the first argument.  A single - (dash) can be   |
    1810  | included in the strings by being the first or the last character  |
    1811  | in the string.  If the first character in a range is after the    |
    1812  | first in the character set, the range is made backwards, thus 9-0 |
    1813  | is the string 9876543210.                                         |
    1814  `------------------------------------------------------------------*/
    1815  
    1816  static const char *
    1817  expand_ranges (const char *s, struct obstack *obs)
    1818  {
    1819    unsigned char from;
    1820    unsigned char to;
    1821  
    1822    for (from = '\0'; *s != '\0'; from = to_uchar (*s++))
    1823      {
    1824        if (*s == '-' && from != '\0')
    1825          {
    1826            to = to_uchar (*++s);
    1827            if (to == '\0')
    1828              {
    1829                /* trailing dash */
    1830                obstack_1grow (obs, '-');
    1831                break;
    1832              }
    1833            else if (from <= to)
    1834              {
    1835                while (from++ < to)
    1836                  obstack_1grow (obs, from);
    1837              }
    1838            else
    1839              {
    1840                while (--from >= to)
    1841                  obstack_1grow (obs, from);
    1842              }
    1843          }
    1844        else
    1845          obstack_1grow (obs, *s);
    1846      }
    1847    obstack_1grow (obs, '\0');
    1848    return (char *) obstack_finish (obs);
    1849  }
    1850  
    1851  /*-----------------------------------------------------------------.
    1852  | The macro "translit" translates all characters in the first      |
    1853  | argument, which are present in the second argument, into the     |
    1854  | corresponding character from the third argument.  If the third   |
    1855  | argument is shorter than the second, the extra characters in the |
    1856  | second argument are deleted from the first.                      |
    1857  `-----------------------------------------------------------------*/
    1858  
    1859  static void
    1860  m4_translit (struct obstack *obs, int argc, token_data **argv)
    1861  {
    1862    const char *data = ARG (1);
    1863    const char *from = ARG (2);
    1864    const char *to;
    1865    char map[UCHAR_MAX + 1];
    1866    char found[UCHAR_MAX + 1];
    1867    unsigned char ch;
    1868  
    1869    if (bad_argc (argv[0], argc, 3, 4) || !*data || !*from)
    1870      {
    1871        /* builtin(`translit') is blank, but translit(`abc') is abc.  */
    1872        if (2 <= argc)
    1873          obstack_grow (obs, data, strlen (data));
    1874        return;
    1875      }
    1876  
    1877    to = ARG (3);
    1878    if (strchr (to, '-') != NULL)
    1879      {
    1880        to = expand_ranges (to, obs);
    1881        assert (to && *to);
    1882      }
    1883  
    1884    /* If there are only one or two bytes to replace, it is faster to
    1885       use memchr2.  Using expand_ranges does nothing unless there are
    1886       at least three bytes.  */
    1887    if (!from[1] || !from[2])
    1888      {
    1889        const char *p;
    1890        size_t len = strlen (data);
    1891        while ((p = (char *) memchr2 (data, from[0], from[1], len)))
    1892          {
    1893            obstack_grow (obs, data, p - data);
    1894            len -= p - data;
    1895            if (!len)
    1896              return;
    1897            data = p + 1;
    1898            len--;
    1899            if (*p == from[0] && to[0])
    1900              obstack_1grow (obs, to[0]);
    1901            else if (*p == from[1] && to[0] && to[1])
    1902              obstack_1grow (obs, to[1]);
    1903          }
    1904        obstack_grow (obs, data, len);
    1905        return;
    1906      }
    1907  
    1908    if (strchr (from, '-') != NULL)
    1909      {
    1910        from = expand_ranges (from, obs);
    1911        assert (from && *from);
    1912      }
    1913  
    1914    /* Calling strchr(from) for each character in data is quadratic,
    1915       since both strings can be arbitrarily long.  Instead, create a
    1916       from-to mapping in one pass of from, then use that map in one
    1917       pass of data, for linear behavior.  Traditional behavior is that
    1918       only the first instance of a character in from is consulted,
    1919       hence the found map.  */
    1920    memset (map, 0, sizeof map);
    1921    memset (found, 0, sizeof found);
    1922    for ( ; (ch = *from) != '\0'; from++)
    1923      {
    1924        if (! found[ch])
    1925          {
    1926            found[ch] = 1;
    1927            map[ch] = *to;
    1928          }
    1929        if (*to != '\0')
    1930          to++;
    1931      }
    1932  
    1933    for (data = ARG (1); (ch = *data) != '\0'; data++)
    1934      {
    1935        if (! found[ch])
    1936          obstack_1grow (obs, ch);
    1937        else if (map[ch])
    1938          obstack_1grow (obs, map[ch]);
    1939      }
    1940  }
    1941  
    1942  /*-------------------------------------------------------------------.
    1943  | Frontend for printf like formatting.  The function format () lives |
    1944  | in the file format.c.                                              |
    1945  `-------------------------------------------------------------------*/
    1946  
    1947  static void
    1948  m4_format (struct obstack *obs, int argc, token_data **argv)
    1949  {
    1950    if (bad_argc (argv[0], argc, 2, -1))
    1951      return;
    1952    expand_format (obs, argc - 1, argv + 1);
    1953  }
    1954  
    1955  /*------------------------------------------------------------------.
    1956  | Function to perform substitution by regular expressions.  Used by |
    1957  | the builtins regexp and patsubst.  The changed text is placed on  |
    1958  | the obstack.  The substitution is REPL, with \& substituted by    |
    1959  | this part of VICTIM matched by the last whole regular expression, |
    1960  | taken from REGS[0], and \N substituted by the text matched by the |
    1961  | Nth parenthesized sub-expression, taken from REGS[N].             |
    1962  `------------------------------------------------------------------*/
    1963  
    1964  static int substitute_warned = 0;
    1965  
    1966  static void
    1967  substitute (struct obstack *obs, const char *victim, const char *repl,
    1968              struct re_registers *regs)
    1969  {
    1970    int ch;
    1971    __re_size_t ind;
    1972    while (1)
    1973      {
    1974        const char *backslash = strchr (repl, '\\');
    1975        if (!backslash)
    1976          {
    1977            obstack_grow (obs, repl, strlen (repl));
    1978            return;
    1979          }
    1980        obstack_grow (obs, repl, backslash - repl);
    1981        repl = backslash;
    1982        ch = *++repl;
    1983        switch (ch)
    1984          {
    1985          case '0':
    1986            if (!substitute_warned)
    1987              {
    1988                M4ERROR ((warning_status, 0, _("\
    1989  Warning: \\0 will disappear, use \\& instead in replacements")));
    1990                substitute_warned = 1;
    1991              }
    1992            FALLTHROUGH;
    1993          case '&':
    1994            obstack_grow (obs, victim + regs->start[0],
    1995                          regs->end[0] - regs->start[0]);
    1996            repl++;
    1997            break;
    1998  
    1999          case '1': case '2': case '3': case '4': case '5': case '6':
    2000          case '7': case '8': case '9':
    2001            ind = ch -= '0';
    2002            if (regs->num_regs - 1 <= ind)
    2003              M4ERROR ((warning_status, 0,
    2004                        _("Warning: sub-expression %d not present"), ch));
    2005            else if (regs->end[ch] > 0)
    2006              obstack_grow (obs, victim + regs->start[ch],
    2007                            regs->end[ch] - regs->start[ch]);
    2008            repl++;
    2009            break;
    2010  
    2011          case '\0':
    2012            M4ERROR ((warning_status, 0,
    2013                      _("Warning: trailing \\ ignored in replacement")));
    2014            return;
    2015  
    2016          default:
    2017            obstack_1grow (obs, ch);
    2018            repl++;
    2019            break;
    2020          }
    2021      }
    2022  }
    2023  
    2024  /*------------------------------------------.
    2025  | Initialize regular expression variables.  |
    2026  `------------------------------------------*/
    2027  
    2028  void
    2029  init_pattern_buffer (struct re_pattern_buffer *buf, struct re_registers *regs)
    2030  {
    2031    buf->translate = NULL;
    2032    buf->fastmap = NULL;
    2033    buf->buffer = NULL;
    2034    buf->allocated = 0;
    2035    if (regs)
    2036      {
    2037        regs->start = NULL;
    2038        regs->end = NULL;
    2039      }
    2040  }
    2041  
    2042  /*------------------------------------------------------------------.
    2043  | Regular expression version of index.  Given two arguments, expand |
    2044  | to the index of the first match of the second argument (a regexp) |
    2045  | in the first.  Expand to -1 if here is no match.  Given a third   |
    2046  | argument, it changes the expansion to this argument.              |
    2047  `------------------------------------------------------------------*/
    2048  
    2049  static void
    2050  m4_regexp (struct obstack *obs, int argc, token_data **argv)
    2051  {
    2052    const char *victim;           /* first argument */
    2053    const char *regexp;           /* regular expression */
    2054    const char *repl;             /* replacement string */
    2055  
    2056    struct re_pattern_buffer buf; /* compiled regular expression */
    2057    struct re_registers regs;     /* for subexpression matches */
    2058    const char *msg;              /* error message from re_compile_pattern */
    2059    int startpos;                 /* start position of match */
    2060    int length;                   /* length of first argument */
    2061  
    2062    if (bad_argc (argv[0], argc, 3, 4))
    2063      {
    2064        /* builtin(`regexp') is blank, but regexp(`abc') is 0.  */
    2065        if (argc == 2)
    2066          shipout_int (obs, 0);
    2067        return;
    2068      }
    2069  
    2070    victim = TOKEN_DATA_TEXT (argv[1]);
    2071    regexp = TOKEN_DATA_TEXT (argv[2]);
    2072  
    2073    init_pattern_buffer (&buf, &regs);
    2074    msg = re_compile_pattern (regexp, strlen (regexp), &buf);
    2075  
    2076    if (msg != NULL)
    2077      {
    2078        M4ERROR ((warning_status, 0,
    2079                  _("bad regular expression: `%s': %s"), regexp, msg));
    2080        free_pattern_buffer (&buf, &regs);
    2081        return;
    2082      }
    2083  
    2084    length = strlen (victim);
    2085    /* Avoid overhead of allocating regs if we won't use it.  */
    2086    startpos = re_search (&buf, victim, length, 0, length,
    2087                          argc == 3 ? NULL : &regs);
    2088  
    2089    if (startpos == -2)
    2090      M4ERROR ((warning_status, 0,
    2091                _("error matching regular expression `%s'"), regexp));
    2092    else if (argc == 3)
    2093      shipout_int (obs, startpos);
    2094    else if (startpos >= 0)
    2095      {
    2096        repl = TOKEN_DATA_TEXT (argv[3]);
    2097        substitute (obs, victim, repl, &regs);
    2098      }
    2099  
    2100    free_pattern_buffer (&buf, &regs);
    2101  }
    2102  
    2103  /*--------------------------------------------------------------------------.
    2104  | Substitute all matches of a regexp occuring in a string.  Each match of   |
    2105  | the second argument (a regexp) in the first argument is changed to the    |
    2106  | third argument, with \& substituted by the matched text, and \N           |
    2107  | substituted by the text matched by the Nth parenthesized sub-expression.  |
    2108  `--------------------------------------------------------------------------*/
    2109  
    2110  static void
    2111  m4_patsubst (struct obstack *obs, int argc, token_data **argv)
    2112  {
    2113    const char *victim;           /* first argument */
    2114    const char *regexp;           /* regular expression */
    2115  
    2116    struct re_pattern_buffer buf; /* compiled regular expression */
    2117    struct re_registers regs;     /* for subexpression matches */
    2118    const char *msg;              /* error message from re_compile_pattern */
    2119    int matchpos;                 /* start position of match */
    2120    int offset;                   /* current match offset */
    2121    int length;                   /* length of first argument */
    2122  
    2123    if (bad_argc (argv[0], argc, 3, 4))
    2124      {
    2125        /* builtin(`patsubst') is blank, but patsubst(`abc') is abc.  */
    2126        if (argc == 2)
    2127          obstack_grow (obs, ARG (1), strlen (ARG (1)));
    2128        return;
    2129      }
    2130  
    2131    regexp = TOKEN_DATA_TEXT (argv[2]);
    2132  
    2133    init_pattern_buffer (&buf, &regs);
    2134    msg = re_compile_pattern (regexp, strlen (regexp), &buf);
    2135  
    2136    if (msg != NULL)
    2137      {
    2138        M4ERROR ((warning_status, 0,
    2139                  _("bad regular expression `%s': %s"), regexp, msg));
    2140        free (buf.buffer);
    2141        return;
    2142      }
    2143  
    2144    victim = TOKEN_DATA_TEXT (argv[1]);
    2145    length = strlen (victim);
    2146  
    2147    offset = 0;
    2148    while (offset <= length)
    2149      {
    2150        matchpos = re_search (&buf, victim, length,
    2151                              offset, length - offset, &regs);
    2152        if (matchpos < 0)
    2153          {
    2154  
    2155            /* Match failed -- either error or there is no match in the
    2156               rest of the string, in which case the rest of the string is
    2157               copied verbatim.  */
    2158  
    2159            if (matchpos == -2)
    2160              M4ERROR ((warning_status, 0,
    2161                        _("error matching regular expression `%s'"), regexp));
    2162            else if (offset < length)
    2163              obstack_grow (obs, victim + offset, length - offset);
    2164            break;
    2165          }
    2166  
    2167        /* Copy the part of the string that was skipped by re_search ().  */
    2168  
    2169        if (matchpos > offset)
    2170          obstack_grow (obs, victim + offset, matchpos - offset);
    2171  
    2172        /* Handle the part of the string that was covered by the match.  */
    2173  
    2174        substitute (obs, victim, ARG (3), &regs);
    2175  
    2176        /* Update the offset to the end of the match.  If the regexp
    2177           matched a null string, advance offset one more, to avoid
    2178           infinite loops.  */
    2179  
    2180        offset = regs.end[0];
    2181        if (regs.start[0] == regs.end[0])
    2182          obstack_1grow (obs, victim[offset++]);
    2183      }
    2184    obstack_1grow (obs, '\0');
    2185  
    2186    free_pattern_buffer (&buf, &regs);
    2187  }
    2188  
    2189  /* Finally, a placeholder builtin.  This builtin is not installed by
    2190     default, but when reading back frozen files, this is associated
    2191     with any builtin we don't recognize (for example, if the frozen
    2192     file was created with a changeword capable m4, but is then loaded
    2193     by a different m4 that does not support changeword).  This way, we
    2194     can keep 'm4 -R' quiet in the common case that the user did not
    2195     know or care about the builtin when the frozen file was created,
    2196     while still flagging it as a potential error if an attempt is made
    2197     to actually use the builtin.  */
    2198  
    2199  /*--------------------------------------------------------------------.
    2200  | Issue a warning that this macro is a placeholder for an unsupported |
    2201  | builtin that was requested while reloading a frozen file.           |
    2202  `--------------------------------------------------------------------*/
    2203  
    2204  void
    2205  m4_placeholder (struct obstack *obs MAYBE_UNUSED, int argc,
    2206                  token_data **argv)
    2207  {
    2208    M4ERROR ((warning_status, 0, _("\
    2209  builtin `%s' requested by frozen file is not supported"), ARG (0)));
    2210  }
    2211  
    2212  /*-------------------------------------------------------------------.
    2213  | This function handles all expansion of user defined and predefined |
    2214  | macros.  It is called with an obstack OBS, where the macros        |
    2215  | expansion will be placed, as an unfinished object.  SYM points to  |
    2216  | the macro definition, giving the expansion text.  ARGC and ARGV    |
    2217  | are the arguments, as usual.                                       |
    2218  `-------------------------------------------------------------------*/
    2219  
    2220  void
    2221  expand_user_macro (struct obstack *obs, symbol *sym,
    2222                     int argc, token_data **argv)
    2223  {
    2224    const char *text = SYMBOL_TEXT (sym);
    2225    int i;
    2226    while (1)
    2227      {
    2228        const char *dollar = strchr (text, '$');
    2229        if (!dollar)
    2230          {
    2231            obstack_grow (obs, text, strlen (text));
    2232            return;
    2233          }
    2234        obstack_grow (obs, text, dollar - text);
    2235        text = dollar;
    2236        switch (*++text)
    2237          {
    2238          case '0': case '1': case '2': case '3': case '4':
    2239          case '5': case '6': case '7': case '8': case '9':
    2240            if (no_gnu_extensions)
    2241              {
    2242                i = *text++ - '0';
    2243              }
    2244            else
    2245              {
    2246                for (i = 0; c_isdigit (*text); text++)
    2247                  i = i*10 + (*text - '0');
    2248              }
    2249            if (i < argc)
    2250              obstack_grow (obs, TOKEN_DATA_TEXT (argv[i]),
    2251                            strlen (TOKEN_DATA_TEXT (argv[i])));
    2252            break;
    2253  
    2254          case '#': /* number of arguments */
    2255            shipout_int (obs, argc - 1);
    2256            text++;
    2257            break;
    2258  
    2259          case '*': /* all arguments */
    2260          case '@': /* ... same, but quoted */
    2261            dump_args (obs, argc, argv, ",", *text == '@');
    2262            text++;
    2263            break;
    2264  
    2265          default:
    2266            obstack_1grow (obs, '$');
    2267            break;
    2268          }
    2269      }
    2270  }