]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl
Merge pull request #27 from terraform-providers/go-modules-2019-02-22
[github/fretlink/terraform-provider-statuscake.git] / vendor / golang.org / x / sys / unix / mksyscall_aix_ppc64.pl
1 #!/usr/bin/env perl
2 # Copyright 2018 The Go Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style
4 # license that can be found in the LICENSE file.
5
6 # This program reads a file containing function prototypes
7 # (like syscall_aix.go) and generates system call bodies.
8 # The prototypes are marked by lines beginning with "//sys"
9 # and read like func declarations if //sys is replaced by func, but:
10 # * The parameter lists must give a name for each argument.
11 # This includes return parameters.
12 # * The parameter lists must give a type for each argument:
13 # the (x, y, z int) shorthand is not allowed.
14 # * If the return parameter is an error number, it must be named err.
15 # * If go func name needs to be different than its libc name,
16 # * or the function is not in libc, name could be specified
17 # * at the end, after "=" sign, like
18 # //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
19
20 # This program will generate three files and handle both gc and gccgo implementation:
21 # - zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation)
22 # - zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6
23 # - zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type.
24
25 # The generated code looks like this
26 #
27 # zsyscall_aix_ppc64.go
28 # func asyscall(...) (n int, err error) {
29 # // Pointer Creation
30 # r1, e1 := callasyscall(...)
31 # // Type Conversion
32 # // Error Handler
33 # return
34 # }
35 #
36 # zsyscall_aix_ppc64_gc.go
37 # //go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o"
38 # //go:linkname libc_asyscall libc_asyscall
39 # var asyscall syscallFunc
40 #
41 # func callasyscall(...) (r1 uintptr, e1 Errno) {
42 # r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... )
43 # return
44 # }
45 #
46 # zsyscall_aix_ppc64_ggcgo.go
47 # /*
48 # int asyscall(...)
49 #
50 # */
51 # import "C"
52 #
53 # func callasyscall(...) (r1 uintptr, e1 Errno) {
54 # r1 = uintptr(C.asyscall(...))
55 # e1 = syscall.GetErrno()
56 # return
57 # }
58
59
60
61 use strict;
62
63 my $cmdline = "mksyscall_aix_ppc64.pl " . join(' ', @ARGV);
64 my $errors = 0;
65 my $_32bit = "";
66 my $tags = ""; # build tags
67 my $aix = 0;
68 my $solaris = 0;
69
70 binmode STDOUT;
71
72 if($ARGV[0] eq "-b32") {
73 $_32bit = "big-endian";
74 shift;
75 } elsif($ARGV[0] eq "-l32") {
76 $_32bit = "little-endian";
77 shift;
78 }
79 if($ARGV[0] eq "-aix") {
80 $aix = 1;
81 shift;
82 }
83 if($ARGV[0] eq "-tags") {
84 shift;
85 $tags = $ARGV[0];
86 shift;
87 }
88
89 if($ARGV[0] =~ /^-/) {
90 print STDERR "usage: mksyscall_aix.pl [-b32 | -l32] [-tags x,y] [file ...]\n";
91 exit 1;
92 }
93
94 sub parseparamlist($) {
95 my ($list) = @_;
96 $list =~ s/^\s*//;
97 $list =~ s/\s*$//;
98 if($list eq "") {
99 return ();
100 }
101 return split(/\s*,\s*/, $list);
102 }
103
104 sub parseparam($) {
105 my ($p) = @_;
106 if($p !~ /^(\S*) (\S*)$/) {
107 print STDERR "$ARGV:$.: malformed parameter: $p\n";
108 $errors = 1;
109 return ("xx", "int");
110 }
111 return ($1, $2);
112 }
113
114 my $package = "";
115 # GCCGO
116 my $textgccgo = "";
117 my $c_extern = "/*\n#include <stdint.h>\n";
118 # GC
119 my $textgc = "";
120 my $dynimports = "";
121 my $linknames = "";
122 my @vars = ();
123 # COMMUN
124 my $textcommon = "";
125
126 while(<>) {
127 chomp;
128 s/\s+/ /g;
129 s/^\s+//;
130 s/\s+$//;
131 $package = $1 if !$package && /^package (\S+)$/;
132 my $nonblock = /^\/\/sysnb /;
133 next if !/^\/\/sys / && !$nonblock;
134
135 # Line must be of the form
136 # func Open(path string, mode int, perm int) (fd int, err error)
137 # Split into name, in params, out params.
138 if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) {
139 print STDERR "$ARGV:$.: malformed //sys declaration\n";
140 $errors = 1;
141 next;
142 }
143 my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6);
144
145 # Split argument lists on comma.
146 my @in = parseparamlist($in);
147 my @out = parseparamlist($out);
148
149 $in = join(', ', @in);
150 $out = join(', ', @out);
151
152 if($sysname eq "") {
153 $sysname = "$func";
154 }
155
156 my $onlyCommon = 0;
157 if ($func eq "readlen" || $func eq "writelen" || $func eq "FcntlInt" || $func eq "FcntlFlock") {
158 # This function call another syscall which is already implemented.
159 # Therefore, the gc and gccgo part must not be generated.
160 $onlyCommon = 1
161 }
162
163 # Try in vain to keep people from editing this file.
164 # The theory is that they jump into the middle of the file
165 # without reading the header.
166
167 $textcommon .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
168 if (!$onlyCommon) {
169 $textgccgo .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
170 $textgc .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
171 }
172
173
174 # Check if value return, err return available
175 my $errvar = "";
176 my $retvar = "";
177 my $rettype = "";
178 foreach my $p (@out) {
179 my ($name, $type) = parseparam($p);
180 if($type eq "error") {
181 $errvar = $name;
182 } else {
183 $retvar = $name;
184 $rettype = $type;
185 }
186 }
187
188
189 $sysname =~ s/([a-z])([A-Z])/${1}_$2/g;
190 $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase.
191
192 # GCCGO Prototype return type
193 my $C_rettype = "";
194 if($rettype eq "unsafe.Pointer") {
195 $C_rettype = "uintptr_t";
196 } elsif($rettype eq "uintptr") {
197 $C_rettype = "uintptr_t";
198 } elsif($rettype =~ /^_/) {
199 $C_rettype = "uintptr_t";
200 } elsif($rettype eq "int") {
201 $C_rettype = "int";
202 } elsif($rettype eq "int32") {
203 $C_rettype = "int";
204 } elsif($rettype eq "int64") {
205 $C_rettype = "long long";
206 } elsif($rettype eq "uint32") {
207 $C_rettype = "unsigned int";
208 } elsif($rettype eq "uint64") {
209 $C_rettype = "unsigned long long";
210 } else {
211 $C_rettype = "int";
212 }
213 if($sysname eq "exit") {
214 $C_rettype = "void";
215 }
216
217 # GCCGO Prototype arguments type
218 my @c_in = ();
219 foreach my $i (0 .. $#in) {
220 my ($name, $type) = parseparam($in[$i]);
221 if($type =~ /^\*/) {
222 push @c_in, "uintptr_t";
223 } elsif($type eq "string") {
224 push @c_in, "uintptr_t";
225 } elsif($type =~ /^\[\](.*)/) {
226 push @c_in, "uintptr_t", "size_t";
227 } elsif($type eq "unsafe.Pointer") {
228 push @c_in, "uintptr_t";
229 } elsif($type eq "uintptr") {
230 push @c_in, "uintptr_t";
231 } elsif($type =~ /^_/) {
232 push @c_in, "uintptr_t";
233 } elsif($type eq "int") {
234 if (($i == 0 || $i == 2) && $func eq "fcntl"){
235 # These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock
236 push @c_in, "uintptr_t";
237 } else {
238 push @c_in, "int";
239 }
240 } elsif($type eq "int32") {
241 push @c_in, "int";
242 } elsif($type eq "int64") {
243 push @c_in, "long long";
244 } elsif($type eq "uint32") {
245 push @c_in, "unsigned int";
246 } elsif($type eq "uint64") {
247 push @c_in, "unsigned long long";
248 } else {
249 push @c_in, "int";
250 }
251 }
252
253 if (!$onlyCommon){
254 # GCCGO Prototype Generation
255 # Imports of system calls from libc
256 $c_extern .= "$C_rettype $sysname";
257 my $c_in = join(', ', @c_in);
258 $c_extern .= "($c_in);\n";
259 }
260
261 # GC Library name
262 if($modname eq "") {
263 $modname = "libc.a/shr_64.o";
264 } else {
265 print STDERR "$func: only syscall using libc are available\n";
266 $errors = 1;
267 next;
268 }
269 my $sysvarname = "libc_${sysname}";
270
271 if (!$onlyCommon){
272 # GC Runtime import of function to allow cross-platform builds.
273 $dynimports .= "//go:cgo_import_dynamic ${sysvarname} ${sysname} \"$modname\"\n";
274 # GC Link symbol to proc address variable.
275 $linknames .= "//go:linkname ${sysvarname} ${sysvarname}\n";
276 # GC Library proc address variable.
277 push @vars, $sysvarname;
278 }
279
280 my $strconvfunc ="BytePtrFromString";
281 my $strconvtype = "*byte";
282
283 # Go function header.
284 if($out ne "") {
285 $out = " ($out)";
286 }
287 if($textcommon ne "") {
288 $textcommon .= "\n"
289 }
290
291 $textcommon .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out ;
292
293 # Prepare arguments to call.
294 my @argscommun = (); # Arguments in the commun part
295 my @argscall = (); # Arguments for call prototype
296 my @argsgc = (); # Arguments for gc call (with syscall6)
297 my @argsgccgo = (); # Arguments for gccgo call (with C.name_of_syscall)
298 my $n = 0;
299 my $arg_n = 0;
300 foreach my $p (@in) {
301 my ($name, $type) = parseparam($p);
302 if($type =~ /^\*/) {
303 push @argscommun, "uintptr(unsafe.Pointer($name))";
304 push @argscall, "$name uintptr";
305 push @argsgc, "$name";
306 push @argsgccgo, "C.uintptr_t($name)";
307 } elsif($type eq "string" && $errvar ne "") {
308 $textcommon .= "\tvar _p$n $strconvtype\n";
309 $textcommon .= "\t_p$n, $errvar = $strconvfunc($name)\n";
310 $textcommon .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
311
312 push @argscommun, "uintptr(unsafe.Pointer(_p$n))";
313 push @argscall, "_p$n uintptr ";
314 push @argsgc, "_p$n";
315 push @argsgccgo, "C.uintptr_t(_p$n)";
316 $n++;
317 } elsif($type eq "string") {
318 print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
319 $textcommon .= "\tvar _p$n $strconvtype\n";
320 $textcommon .= "\t_p$n, $errvar = $strconvfunc($name)\n";
321 $textcommon .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
322
323 push @argscommun, "uintptr(unsafe.Pointer(_p$n))";
324 push @argscall, "_p$n uintptr";
325 push @argsgc, "_p$n";
326 push @argsgccgo, "C.uintptr_t(_p$n)";
327 $n++;
328 } elsif($type =~ /^\[\](.*)/) {
329 # Convert slice into pointer, length.
330 # Have to be careful not to take address of &a[0] if len == 0:
331 # pass nil in that case.
332 $textcommon .= "\tvar _p$n *$1\n";
333 $textcommon .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n";
334 push @argscommun, "uintptr(unsafe.Pointer(_p$n))", "len($name)";
335 push @argscall, "_p$n uintptr", "_lenp$n int";
336 push @argsgc, "_p$n", "uintptr(_lenp$n)";
337 push @argsgccgo, "C.uintptr_t(_p$n)", "C.size_t(_lenp$n)";
338 $n++;
339 } elsif($type eq "int64" && $_32bit ne "") {
340 print STDERR "$ARGV:$.: $func uses int64 with 32 bits mode. Case not yet implemented\n";
341 # if($_32bit eq "big-endian") {
342 # push @args, "uintptr($name >> 32)", "uintptr($name)";
343 # } else {
344 # push @args, "uintptr($name)", "uintptr($name >> 32)";
345 # }
346 # $n++;
347 } elsif($type eq "bool") {
348 print STDERR "$ARGV:$.: $func uses bool. Case not yet implemented\n";
349 # $text .= "\tvar _p$n uint32\n";
350 # $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n";
351 # push @args, "_p$n";
352 # $n++;
353 } elsif($type =~ /^_/ ||$type eq "unsafe.Pointer") {
354 push @argscommun, "uintptr($name)";
355 push @argscall, "$name uintptr";
356 push @argsgc, "$name";
357 push @argsgccgo, "C.uintptr_t($name)";
358 } elsif($type eq "int") {
359 if (($arg_n == 0 || $arg_n == 2) && ($func eq "fcntl" || $func eq "FcntlInt" || $func eq "FcntlFlock")) {
360 # These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock
361 push @argscommun, "uintptr($name)";
362 push @argscall, "$name uintptr";
363 push @argsgc, "$name";
364 push @argsgccgo, "C.uintptr_t($name)";
365 } else {
366 push @argscommun, "$name";
367 push @argscall, "$name int";
368 push @argsgc, "uintptr($name)";
369 push @argsgccgo, "C.int($name)";
370 }
371 } elsif($type eq "int32") {
372 push @argscommun, "$name";
373 push @argscall, "$name int32";
374 push @argsgc, "uintptr($name)";
375 push @argsgccgo, "C.int($name)";
376 } elsif($type eq "int64") {
377 push @argscommun, "$name";
378 push @argscall, "$name int64";
379 push @argsgc, "uintptr($name)";
380 push @argsgccgo, "C.longlong($name)";
381 } elsif($type eq "uint32") {
382 push @argscommun, "$name";
383 push @argscall, "$name uint32";
384 push @argsgc, "uintptr($name)";
385 push @argsgccgo, "C.uint($name)";
386 } elsif($type eq "uint64") {
387 push @argscommun, "$name";
388 push @argscall, "$name uint64";
389 push @argsgc, "uintptr($name)";
390 push @argsgccgo, "C.ulonglong($name)";
391 } elsif($type eq "uintptr") {
392 push @argscommun, "$name";
393 push @argscall, "$name uintptr";
394 push @argsgc, "$name";
395 push @argsgccgo, "C.uintptr_t($name)";
396 } else {
397 push @argscommun, "int($name)";
398 push @argscall, "$name int";
399 push @argsgc, "uintptr($name)";
400 push @argsgccgo, "C.int($name)";
401 }
402 $arg_n++;
403 }
404 my $nargs = @argsgc;
405
406 # COMMUN function generation
407 my $argscommun = join(', ', @argscommun);
408 my $callcommun = "call$sysname($argscommun)";
409 my @ret = ("_", "_");
410 my $body = "";
411 my $do_errno = 0;
412 for(my $i=0; $i<@out; $i++) {
413 my $p = $out[$i];
414 my ($name, $type) = parseparam($p);
415 my $reg = "";
416 if($name eq "err") {
417 $reg = "e1";
418 $ret[1] = $reg;
419 $do_errno = 1;
420 } else {
421 $reg = "r0";
422 $ret[0] = $reg;
423 }
424 if($type eq "bool") {
425 $reg = "$reg != 0";
426 }
427 if($reg ne "e1") {
428 $body .= "\t$name = $type($reg)\n";
429 }
430 }
431 if ($ret[0] eq "_" && $ret[1] eq "_") {
432 $textcommon .= "\t$callcommun\n";
433 } else {
434 $textcommon .= "\t$ret[0], $ret[1] := $callcommun\n";
435 }
436 $textcommon .= $body;
437
438 if ($do_errno) {
439 $textcommon .= "\tif e1 != 0 {\n";
440 $textcommon .= "\t\terr = errnoErr(e1)\n";
441 $textcommon .= "\t}\n";
442 }
443 $textcommon .= "\treturn\n";
444 $textcommon .= "}\n";
445
446 if ($onlyCommon){
447 next
448 }
449 # CALL Prototype
450 my $callProto = sprintf "func call%s(%s) (r1 uintptr, e1 Errno) {\n", $sysname, join(', ', @argscall);
451
452 # GC function generation
453 my $asm = "syscall6";
454 if ($nonblock) {
455 $asm = "rawSyscall6";
456 }
457
458 if(@argsgc <= 6) {
459 while(@argsgc < 6) {
460 push @argsgc, "0";
461 }
462 } else {
463 print STDERR "$ARGV:$.: too many arguments to system call\n";
464 }
465 my $argsgc = join(', ', @argsgc);
466 my $callgc = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $argsgc)";
467
468 $textgc .= $callProto;
469 $textgc .= "\tr1, _, e1 = $callgc\n";
470 $textgc .= "\treturn\n}\n";
471
472 # GCCGO function generation
473 my $argsgccgo = join(', ', @argsgccgo);
474 my $callgccgo = "C.$sysname($argsgccgo)";
475 $textgccgo .= $callProto;
476 $textgccgo .= "\tr1 = uintptr($callgccgo)\n";
477 $textgccgo .= "\te1 = syscall.GetErrno()\n";
478 $textgccgo .= "\treturn\n}\n";
479 }
480
481 if($errors) {
482 exit 1;
483 }
484
485 # Print zsyscall_aix_ppc64.go
486 open(my $fcommun, '>', 'zsyscall_aix_ppc64.go');
487 my $tofcommun = <<EOF;
488 // $cmdline
489 // Code generated by the command above; see README.md. DO NOT EDIT.
490
491 // +build $tags
492
493 package $package
494
495 import (
496 "unsafe"
497 )
498
499 EOF
500
501 $tofcommun .= "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
502
503 $tofcommun .=<<EOF;
504
505 $textcommon
506 EOF
507 print $fcommun $tofcommun;
508
509
510 # Print zsyscall_aix_ppc64_gc.go
511 open(my $fgc, '>', 'zsyscall_aix_ppc64_gc.go');
512 my $tofgc = <<EOF;
513 // $cmdline
514 // Code generated by the command above; see README.md. DO NOT EDIT.
515
516 // +build $tags
517 // +build !gccgo
518
519 package $package
520
521 import (
522 "unsafe"
523 )
524
525
526 EOF
527
528 $tofgc .= "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
529
530 my $vardecls = "\t" . join(",\n\t", @vars);
531 $vardecls .= " syscallFunc";
532
533 $tofgc .=<<EOF;
534 $dynimports
535 $linknames
536 type syscallFunc uintptr
537
538 var (
539 $vardecls
540 )
541
542 // Implemented in runtime/syscall_aix.go.
543 func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
544 func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
545
546 $textgc
547 EOF
548 print $fgc $tofgc;
549
550 # Print zsyscall_aix_ppc64_gc.go
551 open(my $fgccgo, '>', 'zsyscall_aix_ppc64_gccgo.go');
552 my $tofgccgo = <<EOF;
553 // $cmdline
554 // Code generated by the command above; see README.md. DO NOT EDIT.
555
556 // +build $tags
557 // +build gccgo
558
559 package $package
560
561
562 $c_extern
563 */
564 import "C"
565 import (
566 "syscall"
567 )
568
569
570 EOF
571
572 $tofgccgo .= "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
573
574 $tofgccgo .=<<EOF;
575
576 $textgccgo
577 EOF
578 print $fgccgo $tofgccgo;
579 exit 0;