|
| 1 | +# Licensed to the .NET Foundation under one or more agreements. |
| 2 | +# The .NET Foundation licenses this file to you under the Apache 2.0 License. |
| 3 | +# See the LICENSE file in the project root for more information. |
| 4 | + |
| 5 | +from generate import generate |
| 6 | + |
| 7 | +num_systems = 3 |
| 8 | +linux_idx, darwin_idx, windows_idx = range(num_systems) |
| 9 | + |
| 10 | +# python3 -c 'import errno;print(dict(sorted(errno.errorcode.items())))' |
| 11 | +errorcode_linux = {1: 'EPERM', 2: 'ENOENT', 3: 'ESRCH', 4: 'EINTR', 5: 'EIO', 6: 'ENXIO', 7: 'E2BIG', 8: 'ENOEXEC', 9: 'EBADF', 10: 'ECHILD', 11: 'EAGAIN', 12: 'ENOMEM', 13: 'EACCES', 14: 'EFAULT', 15: 'ENOTBLK', 16: 'EBUSY', 17: 'EEXIST', 18: 'EXDEV', 19: 'ENODEV', 20: 'ENOTDIR', 21: 'EISDIR', 22: 'EINVAL', 23: 'ENFILE', 24: 'EMFILE', 25: 'ENOTTY', 26: 'ETXTBSY', 27: 'EFBIG', 28: 'ENOSPC', 29: 'ESPIPE', 30: 'EROFS', 31: 'EMLINK', 32: 'EPIPE', 33: 'EDOM', 34: 'ERANGE', 35: 'EDEADLOCK', 36: 'ENAMETOOLONG', 37: 'ENOLCK', 38: 'ENOSYS', 39: 'ENOTEMPTY', 40: 'ELOOP', 42: 'ENOMSG', 43: 'EIDRM', 44: 'ECHRNG', 45: 'EL2NSYNC', 46: 'EL3HLT', 47: 'EL3RST', 48: 'ELNRNG', 49: 'EUNATCH', 50: 'ENOCSI', 51: 'EL2HLT', 52: 'EBADE', 53: 'EBADR', 54: 'EXFULL', 55: 'ENOANO', 56: 'EBADRQC', 57: 'EBADSLT', 59: 'EBFONT', 60: 'ENOSTR', 61: 'ENODATA', 62: 'ETIME', 63: 'ENOSR', 64: 'ENONET', 65: 'ENOPKG', 66: 'EREMOTE', 67: 'ENOLINK', 68: 'EADV', 69: 'ESRMNT', 70: 'ECOMM', 71: 'EPROTO', 72: 'EMULTIHOP', 73: 'EDOTDOT', 74: 'EBADMSG', 75: 'EOVERFLOW', 76: 'ENOTUNIQ', 77: 'EBADFD', 78: 'EREMCHG', 79: 'ELIBACC', 80: 'ELIBBAD', 81: 'ELIBSCN', 82: 'ELIBMAX', 83: 'ELIBEXEC', 84: 'EILSEQ', 85: 'ERESTART', 86: 'ESTRPIPE', 87: 'EUSERS', 88: 'ENOTSOCK', 89: 'EDESTADDRREQ', 90: 'EMSGSIZE', 91: 'EPROTOTYPE', 92: 'ENOPROTOOPT', 93: 'EPROTONOSUPPORT', 94: 'ESOCKTNOSUPPORT', 95: 'ENOTSUP', 96: 'EPFNOSUPPORT', 97: 'EAFNOSUPPORT', 98: 'EADDRINUSE', 99: 'EADDRNOTAVAIL', 100: 'ENETDOWN', 101: 'ENETUNREACH', 102: 'ENETRESET', 103: 'ECONNABORTED', 104: 'ECONNRESET', 105: 'ENOBUFS', 106: 'EISCONN', 107: 'ENOTCONN', 108: 'ESHUTDOWN', 109: 'ETOOMANYREFS', 110: 'ETIMEDOUT', 111: 'ECONNREFUSED', 112: 'EHOSTDOWN', 113: 'EHOSTUNREACH', 114: 'EALREADY', 115: 'EINPROGRESS', 116: 'ESTALE', 117: 'EUCLEAN', 118: 'ENOTNAM', 119: 'ENAVAIL', 120: 'EISNAM', 121: 'EREMOTEIO', 122: 'EDQUOT', 123: 'ENOMEDIUM', 124: 'EMEDIUMTYPE', 125: 'ECANCELED', 126: 'ENOKEY', 127: 'EKEYEXPIRED', 128: 'EKEYREVOKED', 129: 'EKEYREJECTED', 130: 'EOWNERDEAD', 131: 'ENOTRECOVERABLE', 132: 'ERFKILL'} |
| 12 | +errorcode_darwin = {1: 'EPERM', 2: 'ENOENT', 3: 'ESRCH', 4: 'EINTR', 5: 'EIO', 6: 'ENXIO', 7: 'E2BIG', 8: 'ENOEXEC', 9: 'EBADF', 10: 'ECHILD', 11: 'EDEADLK', 12: 'ENOMEM', 13: 'EACCES', 14: 'EFAULT', 15: 'ENOTBLK', 16: 'EBUSY', 17: 'EEXIST', 18: 'EXDEV', 19: 'ENODEV', 20: 'ENOTDIR', 21: 'EISDIR', 22: 'EINVAL', 23: 'ENFILE', 24: 'EMFILE', 25: 'ENOTTY', 26: 'ETXTBSY', 27: 'EFBIG', 28: 'ENOSPC', 29: 'ESPIPE', 30: 'EROFS', 31: 'EMLINK', 32: 'EPIPE', 33: 'EDOM', 34: 'ERANGE', 35: 'EAGAIN', 36: 'EINPROGRESS', 37: 'EALREADY', 38: 'ENOTSOCK', 39: 'EDESTADDRREQ', 40: 'EMSGSIZE', 41: 'EPROTOTYPE', 42: 'ENOPROTOOPT', 43: 'EPROTONOSUPPORT', 44: 'ESOCKTNOSUPPORT', 45: 'ENOTSUP', 46: 'EPFNOSUPPORT', 47: 'EAFNOSUPPORT', 48: 'EADDRINUSE', 49: 'EADDRNOTAVAIL', 50: 'ENETDOWN', 51: 'ENETUNREACH', 52: 'ENETRESET', 53: 'ECONNABORTED', 54: 'ECONNRESET', 55: 'ENOBUFS', 56: 'EISCONN', 57: 'ENOTCONN', 58: 'ESHUTDOWN', 59: 'ETOOMANYREFS', 60: 'ETIMEDOUT', 61: 'ECONNREFUSED', 62: 'ELOOP', 63: 'ENAMETOOLONG', 64: 'EHOSTDOWN', 65: 'EHOSTUNREACH', 66: 'ENOTEMPTY', 67: 'EPROCLIM', 68: 'EUSERS', 69: 'EDQUOT', 70: 'ESTALE', 71: 'EREMOTE', 72: 'EBADRPC', 73: 'ERPCMISMATCH', 74: 'EPROGUNAVAIL', 75: 'EPROGMISMATCH', 76: 'EPROCUNAVAIL', 77: 'ENOLCK', 78: 'ENOSYS', 79: 'EFTYPE', 80: 'EAUTH', 81: 'ENEEDAUTH', 82: 'EPWROFF', 83: 'EDEVERR', 84: 'EOVERFLOW', 85: 'EBADEXEC', 86: 'EBADARCH', 87: 'ESHLIBVERS', 88: 'EBADMACHO', 89: 'ECANCELED', 90: 'EIDRM', 91: 'ENOMSG', 92: 'EILSEQ', 93: 'ENOATTR', 94: 'EBADMSG', 95: 'EMULTIHOP', 96: 'ENODATA', 97: 'ENOLINK', 98: 'ENOSR', 99: 'ENOSTR', 100: 'EPROTO', 101: 'ETIME', 102: 'EOPNOTSUPP', 103: 'ENOPOLICY', 104: 'ENOTRECOVERABLE', 105: 'EOWNERDEAD'} |
| 13 | +errorcode_windows = {1: 'EPERM', 2: 'ENOENT', 3: 'ESRCH', 4: 'EINTR', 5: 'EIO', 6: 'ENXIO', 7: 'E2BIG', 8: 'ENOEXEC', 9: 'EBADF', 10: 'ECHILD', 11: 'EAGAIN', 12: 'ENOMEM', 13: 'EACCES', 14: 'EFAULT', 16: 'EBUSY', 17: 'EEXIST', 18: 'EXDEV', 19: 'ENODEV', 20: 'ENOTDIR', 21: 'EISDIR', 22: 'EINVAL', 23: 'ENFILE', 24: 'EMFILE', 25: 'ENOTTY', 27: 'EFBIG', 28: 'ENOSPC', 29: 'ESPIPE', 30: 'EROFS', 31: 'EMLINK', 32: 'EPIPE', 33: 'EDOM', 34: 'ERANGE', 36: 'EDEADLOCK', 38: 'ENAMETOOLONG', 39: 'ENOLCK', 40: 'ENOSYS', 41: 'ENOTEMPTY', 42: 'EILSEQ', 104: 'EBADMSG', 105: 'ECANCELED', 111: 'EIDRM', 120: 'ENODATA', 121: 'ENOLINK', 122: 'ENOMSG', 124: 'ENOSR', 125: 'ENOSTR', 127: 'ENOTRECOVERABLE', 129: 'ENOTSUP', 132: 'EOVERFLOW', 133: 'EOWNERDEAD', 134: 'EPROTO', 137: 'ETIME', 139: 'ETXTBSY', 10000: 'WSABASEERR', 10004: 'WSAEINTR', 10009: 'WSAEBADF', 10013: 'WSAEACCES', 10014: 'WSAEFAULT', 10022: 'WSAEINVAL', 10024: 'WSAEMFILE', 10035: 'WSAEWOULDBLOCK', 10036: 'WSAEINPROGRESS', 10037: 'WSAEALREADY', 10038: 'WSAENOTSOCK', 10039: 'WSAEDESTADDRREQ', 10040: 'WSAEMSGSIZE', 10041: 'WSAEPROTOTYPE', 10042: 'WSAENOPROTOOPT', 10043: 'WSAEPROTONOSUPPORT', 10044: 'WSAESOCKTNOSUPPORT', 10045: 'WSAEOPNOTSUPP', 10046: 'WSAEPFNOSUPPORT', 10047: 'WSAEAFNOSUPPORT', 10048: 'WSAEADDRINUSE', 10049: 'WSAEADDRNOTAVAIL', 10050: 'WSAENETDOWN', 10051: 'WSAENETUNREACH', 10052: 'WSAENETRESET', 10053: 'WSAECONNABORTED', 10054: 'WSAECONNRESET', 10055: 'WSAENOBUFS', 10056: 'WSAEISCONN', 10057: 'WSAENOTCONN', 10058: 'WSAESHUTDOWN', 10059: 'WSAETOOMANYREFS', 10060: 'WSAETIMEDOUT', 10061: 'WSAECONNREFUSED', 10062: 'WSAELOOP', 10063: 'WSAENAMETOOLONG', 10064: 'WSAEHOSTDOWN', 10065: 'WSAEHOSTUNREACH', 10066: 'WSAENOTEMPTY', 10067: 'WSAEPROCLIM', 10068: 'WSAEUSERS', 10069: 'WSAEDQUOT', 10070: 'WSAESTALE', 10071: 'WSAEREMOTE', 10091: 'WSASYSNOTREADY', 10092: 'WSAVERNOTSUPPORTED', 10093: 'WSANOTINITIALISED', 10101: 'WSAEDISCON'} |
| 14 | +linux_aliases = {'EOPNOTSUPP' : 'ENOTSUP', 'EDEADLK': 'EDEADLOCK', 'EWOULDBLOCK': 'EAGAIN'} |
| 15 | +darwin_aliases = {'EWOULDBLOCK': 'EAGAIN'} |
| 16 | +aliases = {**linux_aliases, **darwin_aliases} |
| 17 | + |
| 18 | +def set_value(errorval, name, value, index): |
| 19 | + if name not in errorval: |
| 20 | + errorval[name] = [None] * num_systems |
| 21 | + errorval[name][index] = value |
| 22 | + |
| 23 | +def collect_errornames(): |
| 24 | + errorval = {} |
| 25 | + for code in errorcode_linux: |
| 26 | + set_value(errorval, errorcode_linux[code], code, linux_idx) |
| 27 | + for code in errorcode_darwin: |
| 28 | + set_value(errorval, errorcode_darwin[code], code, darwin_idx) |
| 29 | + for code in errorcode_windows: |
| 30 | + set_value(errorval, errorcode_windows[code], code, windows_idx) |
| 31 | + |
| 32 | + # WSA-codes are also available as E-codes if such code name is in use on Posix systems. |
| 33 | + known_symbols = set(errorval) | set(aliases) |
| 34 | + for symbol in errorcode_windows.values(): |
| 35 | + esymbol = symbol[3:] |
| 36 | + if symbol.startswith("WSAE") and esymbol in known_symbols and (esymbol not in errorval or not errorval[esymbol][windows_idx]): |
| 37 | + set_value(errorval, esymbol, errorval[symbol][windows_idx], windows_idx) |
| 38 | + |
| 39 | + # set aliases |
| 40 | + for alias, target in aliases.items(): |
| 41 | + for idx in range(num_systems): |
| 42 | + if errorval[target][idx] and not errorval[alias][idx]: |
| 43 | + errorval[alias][idx] = errorval[target][idx] |
| 44 | + |
| 45 | + return errorval |
| 46 | + |
| 47 | +errorvalues = collect_errornames() |
| 48 | + |
| 49 | +def generate_errno_codes(cw): |
| 50 | + def priority(error): |
| 51 | + codes = errorvalues[error] |
| 52 | + shifts = 0 |
| 53 | + while codes[0] is None: |
| 54 | + codes = codes[1:] + [0] |
| 55 | + shifts += 1 |
| 56 | + res = 0 |
| 57 | + for code in codes: |
| 58 | + res *= 100000 |
| 59 | + res += code if code else 0 |
| 60 | + return res + shifts * 100000 ** (num_systems - 1) // 10 |
| 61 | + |
| 62 | + names = sorted(errorvalues, key = priority) |
| 63 | + for name in names: |
| 64 | + codes = errorvalues[name] |
| 65 | + hidden_on = [] |
| 66 | + cw.writeline() |
| 67 | + if not codes[windows_idx]: |
| 68 | + hidden_on = ["PlatformsAttribute.PlatformFamily.Windows"] |
| 69 | + if not codes[linux_idx] and not codes[darwin_idx]: |
| 70 | + assert not hidden_on, "Cannot hide on both Unix and Windows" |
| 71 | + hidden_on = ["PlatformsAttribute.PlatformFamily.Unix"] |
| 72 | + else: |
| 73 | + if not codes[linux_idx]: |
| 74 | + hidden_on += ["PlatformID.Unix"] |
| 75 | + if not codes[darwin_idx]: |
| 76 | + hidden_on += ["PlatformID.MacOSX"] |
| 77 | + if hidden_on: |
| 78 | + cw.write(f"[PythonHidden({', '.join(hidden_on)})]") |
| 79 | + |
| 80 | + value = windows_code_expr(codes) |
| 81 | + cw.write(f"public static int {name} => {value};") |
| 82 | + |
| 83 | +def windows_code_expr(codes): |
| 84 | + if codes[windows_idx]: |
| 85 | + if not any(codes[:windows_idx]) or all(map(lambda x: x == codes[windows_idx], codes[:windows_idx])): |
| 86 | + return str(codes[windows_idx]) |
| 87 | + else: |
| 88 | + return f"RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? {codes[windows_idx]} : {darwin_code_expr(codes)}" |
| 89 | + else: |
| 90 | + return darwin_code_expr(codes) |
| 91 | + |
| 92 | +def darwin_code_expr(codes): |
| 93 | + if codes[darwin_idx]: |
| 94 | + if not any(codes[:darwin_idx]) or all(map(lambda x: x == codes[darwin_idx], codes[:darwin_idx])): |
| 95 | + return str(codes[darwin_idx]) |
| 96 | + else: |
| 97 | + return f"RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? {codes[darwin_idx]} : {linux_code_expr(codes)}" |
| 98 | + else: |
| 99 | + return linux_code_expr(codes) |
| 100 | + |
| 101 | +def linux_code_expr(codes): |
| 102 | + return str(codes[linux_idx]) |
| 103 | + |
| 104 | +def generate_errno_names(cw): |
| 105 | + def is_windows_alias(name): |
| 106 | + return "WSA" + name in errorvalues and name in errorvalues and errorvalues["WSA" + name][windows_idx] == errorvalues[name][windows_idx] |
| 107 | + |
| 108 | + cw.write("// names defined on all platforms") |
| 109 | + exclusions = set(aliases) |
| 110 | + common_names = sorted(name for name in errorvalues if all(errorvalues[name]) and not is_windows_alias(name) and name not in exclusions) |
| 111 | + for name in common_names: |
| 112 | + cw.write(f'errorcode[{name}] = "{name}";') |
| 113 | + |
| 114 | + cw.write("// names defined on Posix platforms") |
| 115 | + exclusions = set(common_names) | set(aliases) |
| 116 | + posix_names = sorted(name for name in errorvalues if errorvalues[name][linux_idx] and errorvalues[name][darwin_idx] and name not in exclusions) |
| 117 | + cw.enter_block("if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))") |
| 118 | + for name in posix_names: |
| 119 | + cw.write(f'errorcode[{name}] = "{name}";') |
| 120 | + cw.exit_block() |
| 121 | + |
| 122 | + cw.write("// names defined on Linux") |
| 123 | + exclusions = set(common_names) | set(posix_names) | set(linux_aliases) |
| 124 | + linux_names = sorted(name for name in errorvalues if errorvalues[name][linux_idx] and name not in exclusions) |
| 125 | + cw.enter_block("if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))") |
| 126 | + for name in linux_names: |
| 127 | + cw.write(f'errorcode[{name}] = "{name}";') |
| 128 | + cw.exit_block() |
| 129 | + |
| 130 | + cw.write("// names defined on macOS") |
| 131 | + exclusions = set(common_names) | set(posix_names) | set(darwin_aliases) |
| 132 | + darwin_names = sorted(name for name in errorvalues if errorvalues[name][darwin_idx] and name not in exclusions) |
| 133 | + cw.enter_block("if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))") |
| 134 | + for name in darwin_names: |
| 135 | + cw.write(f'errorcode[{name}] = "{name}";') |
| 136 | + cw.exit_block() |
| 137 | + |
| 138 | + cw.write("// names defined on Windows") |
| 139 | + windows_names = sorted(name for name in errorvalues if errorvalues[name][windows_idx] and name not in common_names) |
| 140 | + cw.enter_block("if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))") |
| 141 | + for name in windows_names: |
| 142 | + cw.write(f'errorcode[{name}] = "{name}";') |
| 143 | + cw.exit_block() |
| 144 | + |
| 145 | +def main(): |
| 146 | + return generate( |
| 147 | + ("Errno Codes", generate_errno_codes), |
| 148 | + ("Errno Names", generate_errno_names), |
| 149 | + ) |
| 150 | + |
| 151 | +if __name__ == "__main__": |
| 152 | + main() |
0 commit comments