about summary refs log tree commit diff
path: root/manual/summary-check.awk
blob: b3e447fa1dd9afa20ac2a1b765507b80936b3c49 (plain) (blame)
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# awk script to create a C file from summary.texinfo
# Copyright (C) 2013 Free Software Foundation, Inc.
# This file is part of the GNU C Library.

# The GNU C Library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.

# The GNU C Library 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
# Lesser General Public License for more details.

# You should have received a copy of the GNU Lesser General Public
# License along with the GNU C Library; if not, see
# <http://www.gnu.org/licenses/>.

# This script groks the summary.texi (summary.awk output) format.
# It produces a compilable C file attempts to refer to each declaration
# in summary.texi so as to verify that the types in the manual match the
# types in the code.

BEGIN {
  wraps["@w{"] = 1;
  wraps["@t{"] = 1;
  wraps["@emph{"] = 1;

  print "/* This file is generated by summary-check.awk; DO NOT EDIT!  */";
  print "";
}

NF == 2 && $1 == "@comment" {
  ident = $2;
  optional = 0;
  next
}
NF == 3 && $1 == "@comment" && $3 = "(optional)" {
  ident = $2;
  optional = 1;
  next
}
NF >= 4 && $1 == "@c" {
  source = $2;
  lineno = $3;
  flavor = $4;
  for (i = 5; i <= NF; ++i)
    flavor = flavor " " $i;
  next
}
$1 == "@item" {
  $1 = "";
  gsub(/@var{[^}]+}/, "");
  gsub(/@dots{}/, "...");
  gsub(/@\*/, " ");
  decl = $0 ";";
  for (wrap in wraps) {
    len = length(wrap);
    while ((first = match(decl, wrap)) > 0) {
      depth = 1;
      for (i = first + len; i < length(decl); ++i) {
        c = substr(decl, i, 1);
        if (c == "{") ++depth;
        else if (c == "}" && --depth == 0) {
          left = substr(decl, 1, first - 1);
          middle = substr(decl, first + len, i - (first + len));
          right = substr(decl, i + 1);
          decl = left middle right;
          break;
        }
      }
    }
  }
  sub(/\.\.\.,.+);/, "...);", decl); # execle
  sub(/\[,[^],]+\]/, ", ...", decl); # open
  next
}

/^@file{/ {
  gsub(/[^a-zA-Z0-9_]/, "", ident);
  undef = 1;
  if (flavor ~ /@defvrx?/) {
    # These are used for feature-test macros.  There is nothing we can test.
    next;
  }
  if (flavor ~ /@itemx?/ || flavor == "@vindex") {
    # These are used for macros, but we have no type information.
    next;
  }
  if (flavor == "@defvar") {
    # These are used for variables, but we have no type information.
    next;
  }
  if (flavor == "@defmac") {
    # These are used for function-like macros, but we have no type information.
    next;
  }
  if (flavor ~ /^@deftypevrx? {Data type}$/ || flavor == "@deftp") {
    # This is a type.  We can just test that it's usable.
    decl = "extern " ident " test_" ident ";";
  }
  else if (flavor ~ /^@deftypevrx?/) {
    # These are used for macros.
    sub(ident, "test_" ident " (void) { return " ident "; }", decl);
    undef = 0
  }

  if (decl ~ /float-type/ || decl ~ /real-floating/) {
    # Special case: these are function-like macros that
    # cannot be redeclared.  There isn't a simple way to test.
    next
  }

  if (ident in seen)
    next;
  seen[ident] = 1

  gsub(/,/, "");
  for (i = 1; i <= NF && $i ~ /@file{[^}]+}/; ++i) {
    header = gensub(/@file{([^}]+)}/, "\\1", 1, $i);
    print "#include", "<" header ">";
  }
  if (optional)
    print "#ifdef", ident;
  else if (undef)
    print "#undef", ident;
  print "#", lineno, "\"" source "\"";
  print decl;
  if (optional)
    print "#endif", "/*", ident, "*/";
}

END {
  print "";
  print "int main (void)";
  print "{";
  print "  return 0;";
  print "}";
}