summaryrefslogtreecommitdiff
path: root/m4/builtin.c
blob: cac3062709c3745e5c19419c02849dd7201865a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/* GNU m4 -- A simple macro processor
   Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1999, 2000, 2005,
   2006, 2007, 2008, 2010 Free Software Foundation, Inc.

   This file is part of GNU M4.

   GNU M4 is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   GNU M4 is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/* Code for all builtin macros, initialisation of symbol table, and
   expansion of user defined macros.  */

#include <config.h>

#include "m4private.h"

/* Comparison function, for use in bsearch, which compares NAME
   against the name of BUILTIN.  */
static int
compare_builtin_name_CB (const void *name, const void *b)
{
  const m4__builtin *builtin = (const m4__builtin *) b;
  return strcmp ((const char *) name, builtin->builtin.name);
}

/* Find the builtin which has NAME.  If MODULE is not NULL, then
   search only in MODULE's builtin table.  The result is a malloc'd
   symbol value, suitable for use in the symbol table or for an
   argument to m4_push_builtin.  */
m4_symbol_value *
m4_builtin_find_by_name (m4_module *module, const char *name)
{
  m4_module *cur = module ? module : m4__module_next (NULL);
  m4__builtin *bp;

  do
    {
      bp = (m4__builtin *) bsearch (name, cur->builtins, cur->builtins_len,
                                    sizeof *bp, compare_builtin_name_CB);
      if (bp)
        {
          m4_symbol_value *token = (m4_symbol_value *) xzalloc (sizeof *token);
          m4__set_symbol_value_builtin (token, bp);
          return token;
        }
    }
  while (!module && (cur = m4__module_next (cur)));

  return NULL;
}

/* Find the builtin which has FUNC.  If MODULE argument is supplied
   then search only in MODULE's builtin table.  The result is a
   malloc'd symbol value, suitable for use in the symbol table or for
   an argument to m4_push_builtin.  */
m4_symbol_value *
m4_builtin_find_by_func (m4_module *module, m4_builtin_func *func)
{
  m4_module *cur = module ? module : m4__module_next (NULL);
  size_t i;

  do
    {
      for (i = 0; i < cur->builtins_len; i++)
        if (cur->builtins[i].builtin.func == func)
          {
            m4_symbol_value *token =
              (m4_symbol_value *) xzalloc (sizeof *token);
            m4__set_symbol_value_builtin (token, &cur->builtins[i]);
            return token;
          }
    }
  while (!module && (cur = m4__module_next (cur)));

  return 0;
}

/* Print a representation of FUNC to OBS, optionally including the
   MODULE it came from.  If FLATTEN, output QUOTES around an empty
   string; if CHAIN, append the builtin to the chain; otherwise print
   the name of FUNC.  */
void
m4__builtin_print (m4_obstack *obs, const m4__builtin *func, bool flatten,
                   m4__symbol_chain **chain, const m4_string_pair *quotes,
                   bool module)
{
  assert (func);
  if (flatten)
    {
      if (quotes)
        {
          obstack_grow (obs, quotes->str1, quotes->len1);
          obstack_grow (obs, quotes->str2, quotes->len2);
        }
      module = false;
    }
  else if (chain)
    m4__append_builtin (obs, func, NULL, chain);
  else
    {
      obstack_1grow (obs, '<');
      obstack_grow (obs, func->builtin.name, strlen (func->builtin.name));
      obstack_1grow (obs, '>');
    }
  if (module)
    {
      const char *text = m4_get_module_name (func->module);
      obstack_1grow (obs, '{');
      obstack_grow (obs, text, strlen (text));
      obstack_1grow (obs, '}');
    }
}