summaryrefslogtreecommitdiffstats
path: root/dependencies/pkg/mod/golang.org/x/sys@v0.1.0/unix/linux/mksysnum.go
blob: ed41ce9a2926cfd5543c4a19d7b294913f118f59 (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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build ignore
// +build ignore

package main

import (
	"bufio"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
)

var (
	goos, goarch string
)

// cmdLine returns this programs's commandline arguments
func cmdLine() string {
	return "go run linux/mksysnum.go " + strings.Join(os.Args[1:], " ")
}

// goBuildTags returns build tags in the go:build format.
func goBuildTags() string {
	return fmt.Sprintf("%s && %s", goarch, goos)
}

// plusBuildTags returns build tags in the +build format.
func plusBuildTags() string {
	return fmt.Sprintf("%s,%s", goarch, goos)
}

func format(name string, num int, offset int) string {
	if num > 999 {
		// ignore deprecated syscalls that are no longer implemented
		// https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/unistd.h?id=refs/heads/master#n716
		return ""
	}
	name = strings.ToUpper(name)
	num = num + offset
	return fmt.Sprintf("	SYS_%s = %d;\n", name, num)
}

func checkErr(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "%v\n", err)
		os.Exit(1)
	}
}

// source string and substring slice for regexp
type re struct {
	str string   // source string
	sub []string // matched sub-string
}

// Match performs regular expression match
func (r *re) Match(exp string) bool {
	r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str)
	if r.sub != nil {
		return true
	}
	return false
}

func main() {
	// Get the OS and architecture (using GOARCH_TARGET if it exists)
	goos = os.Getenv("GOOS")
	goarch = os.Getenv("GOARCH_TARGET")
	if goarch == "" {
		goarch = os.Getenv("GOARCH")
	}
	// Check if GOOS and GOARCH environment variables are defined
	if goarch == "" || goos == "" {
		fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
		os.Exit(1)
	}
	// Check that we are using the new build system if we should
	if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
		fmt.Fprintf(os.Stderr, "In the new build system, mksysnum should not be called directly.\n")
		fmt.Fprintf(os.Stderr, "See README.md\n")
		os.Exit(1)
	}

	cc := os.Getenv("CC")
	if cc == "" {
		fmt.Fprintf(os.Stderr, "CC is not defined in environment\n")
		os.Exit(1)
	}
	args := os.Args[1:]
	args = append([]string{"-E", "-dD"}, args...)
	cmd, err := exec.Command(cc, args...).Output() // execute command and capture output
	if err != nil {
		fmt.Fprintf(os.Stderr, "can't run %s", cc)
		os.Exit(1)
	}
	text := ""
	s := bufio.NewScanner(strings.NewReader(string(cmd)))
	var offset, prev int
	for s.Scan() {
		t := re{str: s.Text()}
		if t.Match(`^#define __NR_Linux\s+([0-9]+)`) {
			// mips/mips64: extract offset
			offset, _ = strconv.Atoi(t.sub[1]) // Make offset=0 if empty or non-numeric
		} else if t.Match(`^#define __NR(\w*)_SYSCALL_BASE\s+([0-9]+)`) {
			// arm: extract offset
			offset, _ = strconv.Atoi(t.sub[1]) // Make offset=0 if empty or non-numeric
		} else if t.Match(`^#define __NR_syscalls\s+`) {
			// ignore redefinitions of __NR_syscalls
		} else if t.Match(`^#define __NR_(\w*)Linux_syscalls\s+`) {
			// mips/mips64: ignore definitions about the number of syscalls
		} else if t.Match(`^#define __NR_(\w+)\s+([0-9]+)`) {
			prev, err = strconv.Atoi(t.sub[2])
			checkErr(err)
			text += format(t.sub[1], prev, offset)
		} else if t.Match(`^#define __NR3264_(\w+)\s+([0-9]+)`) {
			prev, err = strconv.Atoi(t.sub[2])
			checkErr(err)
			text += format(t.sub[1], prev, offset)
		} else if t.Match(`^#define __NR_(\w+)\s+\(\w+\+\s*([0-9]+)\)`) {
			r2, err := strconv.Atoi(t.sub[2])
			checkErr(err)
			text += format(t.sub[1], prev+r2, offset)
		} else if t.Match(`^#define __NR_(\w+)\s+\(__NR_(?:SYSCALL_BASE|Linux) \+ ([0-9]+)`) {
			r2, err := strconv.Atoi(t.sub[2])
			checkErr(err)
			text += format(t.sub[1], r2, offset)
		}
	}
	err = s.Err()
	checkErr(err)
	fmt.Printf(template, cmdLine(), goBuildTags(), plusBuildTags(), text)
}

const template = `// %s
// Code generated by the command above; see README.md. DO NOT EDIT.

//go:build %s
// +build %s

package unix

const(
%s)`