makesyscalls.sh revision 1.25 1 #! /bin/sh -
2 # $NetBSD: makesyscalls.sh,v 1.25 1998/01/09 06:07:26 thorpej Exp $
3 #
4 # Copyright (c) 1994,1996 Christopher G. Demetriou
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
10 # 1. Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # 2. Redistributions in binary form must reproduce the above copyright
13 # notice, this list of conditions and the following disclaimer in the
14 # documentation and/or other materials provided with the distribution.
15 # 3. All advertising materials mentioning features or use of this software
16 # must display the following acknowledgement:
17 # This product includes software developed for the NetBSD Project
18 # by Christopher G. Demetriou.
19 # 4. The name of the author may not be used to endorse or promote products
20 # derived from this software without specific prior written permission
21 #
22 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 # @(#)makesyscalls.sh 8.1 (Berkeley) 6/10/93
34
35 set -e
36
37 case $# in
38 2) ;;
39 *) echo "Usage: $0 config-file input-file" 1>&2
40 exit 1
41 ;;
42 esac
43
44 # source the config file.
45 . $1
46
47 # the config file sets the following variables:
48 # sysnames the syscall names file
49 # sysnumhdr the syscall numbers file
50 # syssw the syscall switch file
51 # sysarghdr the syscall argument struct definitions
52 # compatopts those syscall types that are for 'compat' syscalls
53 # switchname the name for the 'struct sysent' we define
54 # namesname the name for the 'char *[]' we define
55 # constprefix the prefix for the system call constants
56 #
57 # NOTE THAT THIS makesyscalls.sh DOES NOT SUPPORT 'LIBCOMPAT'.
58
59 # tmp files:
60 sysdcl="sysent.dcl"
61 sysprotos="sys.protos"
62 syscompat_pref="sysent."
63 sysent="sysent.switch"
64
65 trap "rm $sysdcl $sysprotos $sysent" 0
66
67 # Awk program (must support nawk extensions)
68 # Use "awk" at Berkeley, "nawk" or "gawk" elsewhere.
69 awk=${AWK:-awk}
70
71 # Does this awk have a "toupper" function? (i.e. is it GNU awk)
72 isgawk=`$awk 'BEGIN { print toupper("true"); exit; }' 2>/dev/null`
73
74 # If this awk does not define "toupper" then define our own.
75 if [ "$isgawk" = TRUE ] ; then
76 # GNU awk provides it.
77 toupper=
78 else
79 # Provide our own toupper()
80 toupper='
81 function toupper(str) {
82 _toupper_cmd = "echo "str" |tr a-z A-Z"
83 _toupper_cmd | getline _toupper_str;
84 close(_toupper_cmd);
85 return _toupper_str;
86 }'
87 fi
88
89 # before handing it off to awk, make a few adjustments:
90 # (1) insert spaces around {, }, (, ), *, and commas.
91 # (2) get rid of any and all dollar signs (so that rcs id use safe)
92 #
93 # The awk script will deal with blank lines and lines that
94 # start with the comment character (';').
95
96 sed -e '
97 s/\$//g
98 :join
99 /\\$/{a\
100
101 N
102 s/\\\n//
103 b join
104 }
105 2,${
106 /^#/!s/\([{}()*,]\)/ \1 /g
107 }
108 ' < $2 | $awk "
109 $toupper
110 BEGIN {
111 # to allow nested #if/#else/#endif sets
112 savedepth = 0
113
114 sysnames = \"$sysnames\"
115 sysprotos = \"$sysprotos\"
116 sysnumhdr = \"$sysnumhdr\"
117 sysarghdr = \"$sysarghdr\"
118 switchname = \"$switchname\"
119 namesname = \"$namesname\"
120 constprefix = \"$constprefix\"
121
122 sysdcl = \"$sysdcl\"
123 syscompat_pref = \"$syscompat_pref\"
124 sysent = \"$sysent\"
125 infile = \"$2\"
126
127 compatopts = \"$compatopts\"
128 "'
129
130 printf "/*\t\$NetBSD\$\t*/\n\n" > sysdcl
131 printf "/*\n * System call switch table.\n *\n" > sysdcl
132 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysdcl
133
134 ncompat = split(compatopts,compat)
135 for (i = 1; i <= ncompat; i++) {
136 compat_upper[i] = toupper(compat[i])
137
138 printf "\n#ifdef %s\n", compat_upper[i] > sysent
139 printf "#define %s(func) __CONCAT(%s_,func)\n", compat[i], \
140 compat[i] > sysent
141 printf "#else\n" > sysent
142 printf "#define %s(func) sys_nosys\n", compat[i] > sysent
143 printf "#endif\n" > sysent
144 }
145
146 printf "/*\t\$NetBSD\$\t*/\n\n" > sysent
147 printf "\n#define\ts(type)\tsizeof(type)\n\n" > sysent
148 printf "struct sysent %s[] = {\n",switchname > sysent
149
150 printf "/*\t\$NetBSD\$\t*/\n\n" > sysnames
151 printf "/*\n * System call names.\n *\n" > sysnames
152 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnames
153
154 printf "\n/*\n * System call prototypes.\n */\n\n" > sysprotos
155
156 printf "/*\t\$NetBSD\$\t*/\n\n" > sysnumhdr
157 printf "/*\n * System call numbers.\n *\n" > sysnumhdr
158 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnumhdr
159
160 printf "/*\t\$NetBSD\$\t*/\n\n" > sysarghdr
161 printf "/*\n * System call argument lists.\n *\n" > sysarghdr
162 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysarghdr
163 }
164 NR == 1 {
165 printf " * created from%s\n */\n\n", $0 > sysdcl
166
167 printf " * created from%s\n */\n\n", $0 > sysnames
168 printf "char *%s[] = {\n",namesname > sysnames
169
170 printf " * created from%s\n */\n\n", $0 > sysnumhdr
171
172 printf " * created from%s\n */\n\n", $0 > sysarghdr
173 printf "#define\tsyscallarg(x)\tunion { x datum; register_t pad; }\n" \
174 > sysarghdr
175 next
176 }
177 NF == 0 || $1 ~ /^;/ {
178 next
179 }
180 $1 ~ /^#[ ]*include/ {
181 print > sysdcl
182 next
183 }
184 $1 ~ /^#[ ]*if/ {
185 print > sysent
186 print > sysprotos
187 print > sysnames
188 savesyscall[++savedepth] = syscall
189 next
190 }
191 $1 ~ /^#[ ]*else/ {
192 print > sysent
193 print > sysprotos
194 print > sysnames
195 if (savedepth <= 0) {
196 printf "%s: line %d: unbalenced #else\n", \
197 infile, NR
198 exit 1
199 }
200 syscall = savesyscall[savedepth]
201 next
202 }
203 $1 ~ /^#/ {
204 if ($1 ~ /^#[ ]*endif/) {
205 if (savedepth <= 0) {
206 printf "%s: line %d: unbalenced #endif\n", \
207 infile, NR
208 exit 1
209 }
210 savedepth--;
211 }
212 print > sysent
213 print > sysprotos
214 print > sysnames
215 next
216 }
217 syscall != $1 {
218 printf "%s: line %d: syscall number out of sync at %d\n", \
219 infile, NR, syscall
220 printf "line is:\n"
221 print
222 exit 1
223 }
224 function parserr(was, wanted) {
225 printf "%s: line %d: unexpected %s (expected %s)\n", \
226 infile, NR, was, wanted
227 exit 1
228 }
229 function parseline() {
230 f=3 # toss number and type
231 if ($NF != "}") {
232 funcalias=$NF
233 end=NF-1
234 } else {
235 funcalias=""
236 end=NF
237 }
238 if ($f != "{")
239 parserr($f, "{")
240 f++
241 if ($end != "}")
242 parserr($end, "}")
243 end--
244 if ($end != ";")
245 parserr($end, ";")
246 end--
247 if ($end != ")")
248 parserr($end, ")")
249 end--
250
251 returntype = oldf = "";
252 do {
253 if (returntype != "" && oldf != "*")
254 returntype = returntype" ";
255 returntype = returntype$f;
256 oldf = $f;
257 f++
258 } while (f < (end - 1) && $(f+1) != "(");
259 if (f == (end - 1)) {
260 parserr($f, "function argument definition (maybe \"(\"?)");
261 }
262
263 funcname=$f
264 if (funcalias == "") {
265 funcalias=funcname
266 sub(/^([^_]+_)*sys_/, "", funcalias)
267 }
268 f++
269
270 if ($f != "(")
271 parserr($f, ")")
272 f++
273
274 argc=0;
275 if (f == end) {
276 if ($f != "void")
277 parserr($f, "argument definition")
278 isvarargs = 0;
279 varargc = 0;
280 return
281 }
282
283 # some system calls (open() and fcntl()) can accept a variable
284 # number of arguments. If syscalls accept a variable number of
285 # arguments, they must still have arguments specified for
286 # the remaining argument "positions," because of the way the
287 # kernel system call argument handling works.
288 #
289 # Indirect system calls, e.g. syscall(), are exceptions to this
290 # rule, since they are handled entirely by machine-dependent code
291 # and do not need argument structures built.
292
293 isvarargs = 0;
294 while (f <= end) {
295 if ($f == "...") {
296 f++;
297 isvarargs = 1;
298 varargc = argc;
299 continue;
300 }
301 argc++
302 argtype[argc]=""
303 oldf=""
304 while (f < end && $(f+1) != ",") {
305 if (argtype[argc] != "" && oldf != "*")
306 argtype[argc] = argtype[argc]" ";
307 argtype[argc] = argtype[argc]$f;
308 oldf = $f;
309 f++
310 }
311 if (argtype[argc] == "")
312 parserr($f, "argument definition")
313 argname[argc]=$f;
314 f += 2; # skip name, and any comma
315 }
316 # must see another argument after varargs notice.
317 if (isvarargs) {
318 if (argc == varargc && $2 != "INDIR")
319 parserr($f, "argument definition")
320 } else
321 varargc = argc;
322 }
323 function putent(nodefs, compatwrap) {
324 # output syscall declaration for switch table. INDIR functions
325 # get none, since they always have sys_nosys() for their table
326 # entries.
327 if (nodefs != "INDIR") {
328 prototype = "__P((struct proc *, void *, register_t *))"
329 if (compatwrap == "")
330 printf("int\t%s\t%s;\n", funcname,
331 prototype) > sysprotos
332 else
333 printf("int\t%s_%s\t%s;\n", compatwrap, funcname,
334 prototype) > sysprotos
335 }
336
337 # output syscall switch entry
338 if (nodefs == "INDIR") {
339 printf("\t{ 0, 0,\n\t sys_nosys },\t\t\t/* %d = %s (indir) */\n", \
340 syscall, funcalias) > sysent
341 } else {
342 # printf("\t{ { %d", argc) > sysent
343 # for (i = 1; i <= argc; i++) {
344 # if (i == 5) # wrap the line
345 # printf(",\n\t ") > sysent
346 # else
347 # printf(", ") > sysent
348 # printf("s(%s)", argtypenospc[i]) > sysent
349 # }
350 printf("\t{ %d, ", argc) > sysent
351 if (argc == 0)
352 printf("0") > sysent
353 else if (compatwrap == "")
354 printf("s(struct %s_args)", funcname) > sysent
355 else
356 printf("s(struct %s_%s_args)", compatwrap,
357 funcname) > sysent
358 if (compatwrap == "")
359 wfn = sprintf("%s", funcname);
360 else
361 wfn = sprintf("%s(%s)", compatwrap, funcname);
362 printf(",\n\t %s },", wfn) > sysent
363 for (i = 0; i < (33 - length(wfn)) / 8; i++)
364 printf("\t") > sysent
365 if (compatwrap == "")
366 printf("/* %d = %s */\n", syscall, funcalias) > sysent
367 else
368 printf("/* %d = %s %s */\n", syscall, compatwrap,
369 funcalias) > sysent
370 }
371
372 # output syscall name for names table
373 if (compatwrap == "")
374 printf("\t\"%s\",\t\t\t/* %d = %s */\n", funcalias, syscall,
375 funcalias) > sysnames
376 else
377 printf("\t\"%s_%s\",\t/* %d = %s %s */\n", compatwrap,
378 funcalias, syscall, compatwrap, funcalias) > sysnames
379
380 # output syscall number of header, if appropriate
381 if (nodefs == "" || nodefs == "NOARGS" || nodefs == "INDIR") {
382 # output a prototype, to be used to generate lint stubs in
383 # libc.
384 printf("/* syscall: \"%s\" ret: \"%s\" args:", funcalias,
385 returntype) > sysnumhdr
386 for (i = 1; i <= varargc; i++)
387 printf(" \"%s\"", argtype[i]) > sysnumhdr
388 if (isvarargs)
389 printf(" \"...\"") > sysnumhdr
390 printf(" */\n") > sysnumhdr
391
392 printf("#define\t%s%s\t%d\n\n", constprefix, funcalias,
393 syscall) > sysnumhdr
394 } else if (nodefs != "NODEF")
395 printf("\t\t\t\t/* %d is %s %s */\n\n", syscall,
396 compatwrap, funcalias) > sysnumhdr
397
398 # output syscall argument structure, if it has arguments
399 if (argc != 0 && nodefs != "NOARGS" && nodefs != "INDIR") {
400 if (compatwrap == "")
401 printf("\nstruct %s_args {\n", funcname) > sysarghdr
402 else
403 printf("\nstruct %s_%s_args {\n", compatwrap,
404 funcname) > sysarghdr
405 for (i = 1; i <= argc; i++)
406 printf("\tsyscallarg(%s) %s;\n", argtype[i],
407 argname[i]) > sysarghdr
408 printf("};\n") > sysarghdr
409 }
410 }
411 $2 == "STD" {
412 parseline()
413 putent("", "");
414 syscall++
415 next
416 }
417 $2 == "NODEF" || $2 == "NOARGS" || $2 == "INDIR" {
418 parseline()
419 putent($2, "")
420 syscall++
421 next
422 }
423 $2 == "OBSOL" || $2 == "UNIMPL" {
424 if ($2 == "OBSOL")
425 comment="obsolete"
426 else
427 comment="unimplemented"
428 for (i = 3; i <= NF; i++)
429 comment=comment " " $i
430
431 printf("\t{ 0, 0,\n\t sys_nosys },\t\t\t/* %d = %s */\n", \
432 syscall, comment) > sysent
433 printf("\t\"#%d (%s)\",\t\t/* %d = %s */\n", \
434 syscall, comment, syscall, comment) > sysnames
435 if ($2 != "UNIMPL")
436 printf("\t\t\t\t/* %d is %s */\n", syscall, comment) > sysnumhdr
437 syscall++
438 next
439 }
440 {
441 for (i = 1; i <= ncompat; i++) {
442 if ($2 == compat_upper[i]) {
443 parseline();
444 putent("COMMENT", compat[i])
445 syscall++
446 next
447 }
448 }
449 printf "%s: line %d: unrecognized keyword %s\n", infile, NR, $2
450 exit 1
451 }
452 END {
453 printf("};\n\n") > sysent
454 printf("};\n") > sysnames
455 printf("#define\t%sMAXSYSCALL\t%d\n", constprefix, syscall) > sysnumhdr
456 } '
457
458 cat $sysprotos >> $sysarghdr
459 cat $sysdcl $sysent > $syssw
460
461 #chmod 444 $sysnames $sysnumhdr $syssw
462