1# Copyright (C) 1991-2022 Free Software Foundation, Inc.
2# This file is part of the GNU C Library.
3
4# The GNU C Library is free software; you can redistribute it and/or
5# modify it under the terms of the GNU Lesser General Public
6# License as published by the Free Software Foundation; either
7# version 2.1 of the License, or (at your option) any later version.
8
9# The GNU C Library is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12# Lesser General Public License for more details.
13
14# You should have received a copy of the GNU Lesser General Public
15# License along with the GNU C Library; if not, see
16# <https://www.gnu.org/licenses/>.
17
18# errno.texinfo contains lines like:
19# @errno{ENOSYS, 123, Function not implemented}
20
21BEGIN {
22    print "/* This file generated by errnos.awk from";
23    for (i = 1; i < ARGC; i++)
24      {
25	arg = ARGV[i];
26	sub(/.*(manual|include)\//, "", arg);
27	if (arg ~ /.*errnos.d/) continue;
28	print "     " arg;
29      }
30    print "   Do not edit this file; edit errnos.awk and regenerate it.  */";
31    print "";
32    print "#ifndef _BITS_ERRNO_H";
33    print "#define _BITS_ERRNO_H 1";
34    print "";
35    print "#if !defined _ERRNO_H";
36    print "# error \"Never include <bits/errno.h> directly; use <errno.h> instead.\"";
37    print "#endif";
38
39    maxerrno = 0;
40    maxerrlen = 0;
41    in_mach_errors = "";
42    seq = 0;
43  }
44
45/^@errno\{/ \
46  {
47    e = substr($1, 8, length($1)-8)
48    if (length(e) > maxerrlen)
49      maxerrlen = length(e);
50    if (e == "EWOULDBLOCK")
51      {
52	econsts[seq] = e;
53	errnos[seq] = "EAGAIN";
54	seq++;
55	next;
56      }
57
58    errno = substr($2, 1, length($2)-1) + 0;
59    if (errno == 0)
60      next;
61    if (errno > 0x3ffff)
62      {
63	printf("%s:%d: errno value %d too large for the Hurd\n",
64	       FILENAME, NR, errno) >> "/dev/stderr";
65	exit 1;
66      }
67    if (errno > maxerrno)
68      maxerrno = errno;
69
70    etext = "";
71    for (i = 3; i <= NF; ++i)
72      etext = etext " " $i;
73    etext = substr(etext, 2, length(etext)-2);
74
75    econsts[seq] = e;
76    errnos[seq] = sprintf("0x%08x", 0x40000000 + errno);
77    etexts[seq] = etext;
78    seq++;
79    next;
80  }
81
82NF == 3 && $1 == "#define" && $2 == "MACH_SEND_IN_PROGRESS" \
83  {
84    in_mach_errors = FILENAME;
85    annot[seq++] = "\n/* Errors from <mach/message.h>.  */";
86  }
87NF == 3 && $1 == "#define" && $2 == "KERN_SUCCESS" \
88  {
89    in_mach_errors = FILENAME;
90    annot[seq++] = "\n/* Errors from <mach/kern_return.h>.  */";
91    next;
92  }
93
94in_mach_errors != "" && $2 == "MACH_IPC_COMPAT" \
95  {
96    in_mach_errors = "";
97  }
98
99# FIXME: mach/message.h and mach/kern_return.h do include error
100# descriptions which we could slurp, but some of them are very long,
101# we would need to word-wrap them.
102in_mach_errors == FILENAME && NF == 3 && $1 == "#define" \
103  {
104    e = "E" $2;
105    if (length(e) > maxerrlen)
106      maxerrlen = length(e);
107    econsts[seq] = e;
108    errnos[seq] = $3;
109    etexts[seq] = "";
110    seq++;
111  }
112
113$1 == "#define" && $2 == "_MACH_MIG_ERRORS_H_" \
114  {
115    in_mig_errors = 1;
116    annot[seq++] = "\n/* Errors from <mach/mig_errors.h>.  */";
117    next;
118  }
119in_mig_errors && $1 == "#endif" && $3 == "_MACH_MIG_ERRORS_H_" \
120  {
121    in_mig_errors = 0;
122  }
123
124(in_mig_errors && $1 == "#define" && $3 <= -300) || \
125(in_device_errors && $1 == "#define" && /D_/ && NF > 3) \
126  {
127    etext = "";
128    for (i = 5; i < NF; ++i)
129      etext = etext " " $i;
130
131    e = "E" $2;
132    if (length(e) > maxerrlen)
133      maxerrlen = length(e);
134    econsts[seq] = e;
135    errnos[seq] = $3;
136    etexts[seq] = substr(etext, 2, length(etext)-1);
137    seq++;
138  }
139
140$1 == "#define" && $2 == "D_SUCCESS" \
141  {
142    in_device_errors = 1;
143    annot[seq++] = "\n/* Errors from <device/device_types.h>.  */";
144    next;
145  }
146in_device_errors && $1 == "#endif" \
147  {
148    in_device_errors = 0;
149  }
150
151function print_errno_enum(maxseq)
152{
153  print "";
154  print "#ifndef __ASSEMBLER__";
155  print "";
156  print "enum __error_t_codes";
157  print "{";
158  print "  /* The value zero always means success and it is perfectly fine";
159  print "     for code to use 0 explicitly (or implicitly, e.g. via Boolean";
160  print "     coercion.)  Having an enum entry for zero both makes the";
161  print "     debugger print the name for error_t-typed zero values, and";
162  print "     prevents the compiler from issuing warnings about 'case 0:'";
163  print "     in a switch on an error_t-typed value.  */";
164  printf("  %-*s = 0,\n", maxerrlen, "ESUCCESS");
165
166  print "";
167  print "  /* The Hurd uses Mach error system 0x10, subsystem 0. */";
168  for (i = 0; i < maxseq; i++)
169    {
170      if (i in annot)
171	print annot[i];
172      else if (i in etexts && etexts[i] != "")
173	printf("  %-*s = %s,\t/* %s */\n",
174	       maxerrlen, econsts[i], errnos[i], etexts[i]);
175      else if (errnos[i] != "EAGAIN")
176	printf("  %-*s = %s,\n", maxerrlen, econsts[i], errnos[i]);
177    }
178
179  print "";
180  print "  /* Because the C standard requires that errno have type 'int',"
181  print "     this enumeration must be a signed type.  */";
182  print "  __FORCE_ERROR_T_CODES_SIGNED = -1";
183  print "};";
184  print "";
185  print "#endif /* not __ASSEMBLER__ */";
186}
187
188function print_errno_defines(maxseq)
189{
190  print "";
191  print "/* The C standard requires that all of the E-constants be"
192  print "   defined as macros.  */"
193  print "";
194  for (i = 0; i < maxseq; i++)
195    {
196      if (i in annot)
197	print annot[i];
198      else
199	printf("#define %-*s %s\n", maxerrlen, econsts[i], errnos[i]);
200    }
201  print "";
202  printf("#define _HURD_ERRNOS %d\n", maxerrno+1);
203}
204
205END \
206  {
207    print_errno_enum(seq);
208    print_errno_defines(seq);
209
210    print "";
211    print "#endif /* bits/errno.h.  */";
212  }
213