David K. Bainbridge | bd6b288 | 2021-08-26 13:31:02 +0000 | [diff] [blame] | 1 | #!/usr/bin/env bash |
| 2 | # Copyright 2009 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 | # Generate Go code listing errors and other #defined constant |
| 7 | # values (ENAMETOOLONG etc.), by asking the preprocessor |
| 8 | # about the definitions. |
| 9 | |
| 10 | unset LANG |
| 11 | export LC_ALL=C |
| 12 | export LC_CTYPE=C |
| 13 | |
| 14 | CC=${CC:-gcc} |
| 15 | |
| 16 | uname=$(uname) |
| 17 | |
| 18 | includes=' |
| 19 | #include <sys/types.h> |
| 20 | #include <sys/file.h> |
| 21 | #include <fcntl.h> |
| 22 | #include <dirent.h> |
| 23 | #include <sys/socket.h> |
| 24 | #include <netinet/in.h> |
| 25 | #include <netinet/ip.h> |
| 26 | #include <netinet/ip6.h> |
| 27 | #include <netinet/tcp.h> |
| 28 | #include <errno.h> |
| 29 | #include <sys/signal.h> |
| 30 | #include <signal.h> |
| 31 | #include <sys/resource.h> |
| 32 | ' |
| 33 | |
| 34 | ccflags="$@" |
| 35 | |
| 36 | # Write go tool cgo -godefs input. |
| 37 | ( |
| 38 | echo package plan9 |
| 39 | echo |
| 40 | echo '/*' |
| 41 | indirect="includes_$(uname)" |
| 42 | echo "${!indirect} $includes" |
| 43 | echo '*/' |
| 44 | echo 'import "C"' |
| 45 | echo |
| 46 | echo 'const (' |
| 47 | |
| 48 | # The gcc command line prints all the #defines |
| 49 | # it encounters while processing the input |
| 50 | echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags | |
| 51 | awk ' |
| 52 | $1 != "#define" || $2 ~ /\(/ || $3 == "" {next} |
| 53 | |
| 54 | $2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers |
| 55 | $2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next} |
| 56 | $2 ~ /^(SCM_SRCRT)$/ {next} |
| 57 | $2 ~ /^(MAP_FAILED)$/ {next} |
| 58 | |
| 59 | $2 !~ /^ETH_/ && |
| 60 | $2 !~ /^EPROC_/ && |
| 61 | $2 !~ /^EQUIV_/ && |
| 62 | $2 !~ /^EXPR_/ && |
| 63 | $2 ~ /^E[A-Z0-9_]+$/ || |
| 64 | $2 ~ /^B[0-9_]+$/ || |
| 65 | $2 ~ /^V[A-Z0-9]+$/ || |
| 66 | $2 ~ /^CS[A-Z0-9]/ || |
| 67 | $2 ~ /^I(SIG|CANON|CRNL|EXTEN|MAXBEL|STRIP|UTF8)$/ || |
| 68 | $2 ~ /^IGN/ || |
| 69 | $2 ~ /^IX(ON|ANY|OFF)$/ || |
| 70 | $2 ~ /^IN(LCR|PCK)$/ || |
| 71 | $2 ~ /(^FLU?SH)|(FLU?SH$)/ || |
| 72 | $2 ~ /^C(LOCAL|READ)$/ || |
| 73 | $2 == "BRKINT" || |
| 74 | $2 == "HUPCL" || |
| 75 | $2 == "PENDIN" || |
| 76 | $2 == "TOSTOP" || |
| 77 | $2 ~ /^PAR/ || |
| 78 | $2 ~ /^SIG[^_]/ || |
| 79 | $2 ~ /^O[CNPFP][A-Z]+[^_][A-Z]+$/ || |
| 80 | $2 ~ /^IN_/ || |
| 81 | $2 ~ /^LOCK_(SH|EX|NB|UN)$/ || |
| 82 | $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ || |
| 83 | $2 == "ICMPV6_FILTER" || |
| 84 | $2 == "SOMAXCONN" || |
| 85 | $2 == "NAME_MAX" || |
| 86 | $2 == "IFNAMSIZ" || |
| 87 | $2 ~ /^CTL_(MAXNAME|NET|QUERY)$/ || |
| 88 | $2 ~ /^SYSCTL_VERS/ || |
| 89 | $2 ~ /^(MS|MNT)_/ || |
| 90 | $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || |
| 91 | $2 ~ /^(O|F|FD|NAME|S|PTRACE|PT)_/ || |
| 92 | $2 ~ /^LINUX_REBOOT_CMD_/ || |
| 93 | $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || |
| 94 | $2 !~ "NLA_TYPE_MASK" && |
| 95 | $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ || |
| 96 | $2 ~ /^SIOC/ || |
| 97 | $2 ~ /^TIOC/ || |
| 98 | $2 !~ "RTF_BITS" && |
| 99 | $2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ || |
| 100 | $2 ~ /^BIOC/ || |
| 101 | $2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ || |
| 102 | $2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|NOFILE|STACK)|RLIM_INFINITY/ || |
| 103 | $2 ~ /^PRIO_(PROCESS|PGRP|USER)/ || |
| 104 | $2 ~ /^CLONE_[A-Z_]+/ || |
| 105 | $2 !~ /^(BPF_TIMEVAL)$/ && |
| 106 | $2 ~ /^(BPF|DLT)_/ || |
| 107 | $2 !~ "WMESGLEN" && |
| 108 | $2 ~ /^W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", $2, $2)} |
| 109 | $2 ~ /^__WCOREFLAG$/ {next} |
| 110 | $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)} |
| 111 | |
| 112 | {next} |
| 113 | ' | sort |
| 114 | |
| 115 | echo ')' |
| 116 | ) >_const.go |
| 117 | |
| 118 | # Pull out the error names for later. |
| 119 | errors=$( |
| 120 | echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags | |
| 121 | awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' | |
| 122 | sort |
| 123 | ) |
| 124 | |
| 125 | # Pull out the signal names for later. |
| 126 | signals=$( |
| 127 | echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags | |
| 128 | awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' | |
| 129 | egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' | |
| 130 | sort |
| 131 | ) |
| 132 | |
| 133 | # Again, writing regexps to a file. |
| 134 | echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags | |
| 135 | awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' | |
| 136 | sort >_error.grep |
| 137 | echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags | |
| 138 | awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' | |
| 139 | egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT)' | |
| 140 | sort >_signal.grep |
| 141 | |
| 142 | echo '// mkerrors.sh' "$@" |
| 143 | echo '// Code generated by the command above; DO NOT EDIT.' |
| 144 | echo |
| 145 | go tool cgo -godefs -- "$@" _const.go >_error.out |
| 146 | cat _error.out | grep -vf _error.grep | grep -vf _signal.grep |
| 147 | echo |
| 148 | echo '// Errors' |
| 149 | echo 'const (' |
| 150 | cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= Errno(\1)/' |
| 151 | echo ')' |
| 152 | |
| 153 | echo |
| 154 | echo '// Signals' |
| 155 | echo 'const (' |
| 156 | cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= Signal(\1)/' |
| 157 | echo ')' |
| 158 | |
| 159 | # Run C program to print error and syscall strings. |
| 160 | ( |
| 161 | echo -E " |
| 162 | #include <stdio.h> |
| 163 | #include <stdlib.h> |
| 164 | #include <errno.h> |
| 165 | #include <ctype.h> |
| 166 | #include <string.h> |
| 167 | #include <signal.h> |
| 168 | |
| 169 | #define nelem(x) (sizeof(x)/sizeof((x)[0])) |
| 170 | |
| 171 | enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below |
| 172 | |
| 173 | int errors[] = { |
| 174 | " |
| 175 | for i in $errors |
| 176 | do |
| 177 | echo -E ' '$i, |
| 178 | done |
| 179 | |
| 180 | echo -E " |
| 181 | }; |
| 182 | |
| 183 | int signals[] = { |
| 184 | " |
| 185 | for i in $signals |
| 186 | do |
| 187 | echo -E ' '$i, |
| 188 | done |
| 189 | |
| 190 | # Use -E because on some systems bash builtin interprets \n itself. |
| 191 | echo -E ' |
| 192 | }; |
| 193 | |
| 194 | static int |
| 195 | intcmp(const void *a, const void *b) |
| 196 | { |
| 197 | return *(int*)a - *(int*)b; |
| 198 | } |
| 199 | |
| 200 | int |
| 201 | main(void) |
| 202 | { |
| 203 | int i, j, e; |
| 204 | char buf[1024], *p; |
| 205 | |
| 206 | printf("\n\n// Error table\n"); |
| 207 | printf("var errors = [...]string {\n"); |
| 208 | qsort(errors, nelem(errors), sizeof errors[0], intcmp); |
| 209 | for(i=0; i<nelem(errors); i++) { |
| 210 | e = errors[i]; |
| 211 | if(i > 0 && errors[i-1] == e) |
| 212 | continue; |
| 213 | strcpy(buf, strerror(e)); |
| 214 | // lowercase first letter: Bad -> bad, but STREAM -> STREAM. |
| 215 | if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) |
| 216 | buf[0] += a - A; |
| 217 | printf("\t%d: \"%s\",\n", e, buf); |
| 218 | } |
| 219 | printf("}\n\n"); |
| 220 | |
| 221 | printf("\n\n// Signal table\n"); |
| 222 | printf("var signals = [...]string {\n"); |
| 223 | qsort(signals, nelem(signals), sizeof signals[0], intcmp); |
| 224 | for(i=0; i<nelem(signals); i++) { |
| 225 | e = signals[i]; |
| 226 | if(i > 0 && signals[i-1] == e) |
| 227 | continue; |
| 228 | strcpy(buf, strsignal(e)); |
| 229 | // lowercase first letter: Bad -> bad, but STREAM -> STREAM. |
| 230 | if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) |
| 231 | buf[0] += a - A; |
| 232 | // cut trailing : number. |
| 233 | p = strrchr(buf, ":"[0]); |
| 234 | if(p) |
| 235 | *p = '\0'; |
| 236 | printf("\t%d: \"%s\",\n", e, buf); |
| 237 | } |
| 238 | printf("}\n\n"); |
| 239 | |
| 240 | return 0; |
| 241 | } |
| 242 | |
| 243 | ' |
| 244 | ) >_errors.c |
| 245 | |
| 246 | $CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out |