Convert POSIX integer value to compile time variable

Sometimes (for example, using strace, gdbetc.) you find that POSIX calls are superimposed errnoon an integer value, and someone wants to know the C compilation time constant (more precisely, the pre-processor definition) to check for it (for example ECHILD) - see, for example, waitpid for a child process does not succeed .

EG in the above related question, the number of integers has 10been returned to errno. I want to go back from this to the line ECHILD. Nothing perroror strerrorgive me ("No child processes" or the like).

Here's an obvious way to do this that doesn't work:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int
main (int argc, char **argv)
{
  printf ("%s\n", strerror (10));
  exit (0);
}

Prints output:

No child processes

not ECHILD, , .

, grep /usr/include?

, , , :

/usr/include , E .

+4
8

C. GCC cpp.

( : , POSIX, GCC, , , )

, :

$ cpp -dM -include /usr/include/errno.h | grep '^#define E' | sed 's/^#define \(E[A-Z0-9]*\)\s*\(.*\)$/\2 \1/g' | sort -n
EAGAIN EWOULDBLOCK
EDEADLK EDEADLOCK
EOPNOTSUPP ENOTSUP
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 EDEADLK
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 EOPNOTSUPP
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
133 EHWPOISON

:

  • . , , . -, , #include -ed ( ) errno.h, , grep '^#define E' , errno cpp. , .
  • , , #define EWOULDBLOCK EAGAIN, Exxxx .
  • , 41. , , , .

script ( Makefile) (, errno-lookup.c) , errno.

+4

perl, , , :

#!/usr/bin/perl -w
use strict;
no strict "refs";
use POSIX qw(:errno_h);

my $code = shift;

my $ns = \%{'POSIX::'};
foreach (keys %$ns) {
    print "$_\n" if /^E(?!XPORT)/ && (${$ns->{$_}}||-1) == $code;
}
+1

EFOO, ( ) <errno.h>, , . EFOO; , EAGAIN EWOULDBLOCK 11. errno EFOO.

160 E* . , . script, C, . - :

#ifdef E2BIG
    printf("E2BIG %d\n", E2BIG);
#endif

C, - "?", .

, , . . , , , Github .

:

E2BIG EACCES EADDRINUSE EADDRNOTAVAIL EADV EAFNOSUPPORT EAGAIN
EALREADY EBADCOOKIE EBADE EBADF EBADFD EBADHANDLE EBADMSG EBADR EBADRQC
EBADSLT EBADTYPE EBFONT EBUSY ECANCELED ECANCELLED ECHILD ECHRNG ECOMM
ECONNABORTED ECONNREFUSED ECONNRESET EDEADLK EDEADLOCK EDESTADDRREQ
EDOM EDOTDOT EDQUOT EEXIST EFAULT EFBIG EHOSTDOWN EHOSTUNREACH EHWPOISON
EIDRM EILSEQ EINIT EINPROGRESS EINTR EINVAL EIO EIOCBQUEUED EIOCBRETRY
EISCONN EISDIR EISNAM EJUKEBOX EKEYEXPIRED EKEYREJECTED EKEYREVOKED
EL2HLT EL2NSYNC EL3HLT EL3RST ELIBACC ELIBBAD ELIBEXEC ELIBMAX ELIBSCN
ELNRNG ELOCKUNMAPPED ELOOP EMAXERRNO EMEDIUMTYPE EMFILE EMLINK EMSGSIZE
EMULTIHOP ENAMETOOLONG ENAVAIL ENETDOWN ENETRESET ENETUNREACH ENFILE
ENOANO ENOBUFS ENOCSI ENODATA ENODEV ENOENT ENOEXEC ENOIOCTLCMD ENOKEY
ENOLCK ENOLINK ENOMEDIUM ENOMEM ENOMSG ENONET ENOPKG ENOPROTOOPT ENOSPC
ENOSR ENOSTR ENOSYM ENOSYS ENOTACTIVE ENOTBLK ENOTCONN ENOTDIR ENOTEMPTY
ENOTNAM ENOTRECOVERABLE ENOTSOCK ENOTSUP ENOTSUPP ENOTSYNC ENOTTY
ENOTUNIQ ENXIO EOPNOTSUPP EOVERFLOW EOWNERDEAD EPERM EPFNOSUPPORT EPIPE
EPROCLIM EPROTO EPROTONOSUPPORT EPROTOTYPE ERANGE EREFUSED EREMCHG EREMDEV
EREMOTE EREMOTEIO EREMOTERELEASE ERESTART ERESTARTNOHAND ERESTARTNOINTR
ERESTARTSYS ERESTART_RESTARTBLOCK ERFKILL EROFS ERREMOTE ESERVERFAULT
ESHUTDOWN ESOCKTNOSUPPORT ESPIPE ESRCH ESRMNT ESTALE ESTRPIPE ETIME
ETIMEDOUT ETOOMANYREFS ETOOSMALL ETXTBSY EUCLEAN EUNATCH EUSERS
EWOULDBLOCK EXDEV EXFULL
+1

strerror() (?) - . , , "E"...

0

: , .

POSIX, , errno.h, .

, , . (http://pubs.opengroup.org/onlinepubs/9699919799/)

gcc, errno.h gcc -dM -E /usr/include/errno.h , include.

, E, , grep, awk .

gcc -dM -E /usr/include/errno.h | awk '$2 ~ /^E/ {print $3 "\t" $2}' - , , .

, abligh, gcc -dM -E /usr/include/errno.h | egrep "^#define E" | cut -c 9- | sort -n -k 2, .

0

, perl:

#!/usr/bin/perl
use strict;
use warnings;
die "Syntax: error ERRORNUM" unless ($#ARGV==0);
open (my $p, "cpp -dM /usr/include/errno.h |") || die ("Cannot preprocess headers: $!");
while (<$p>)
{
    chomp;
    print "$1\n" if /^#define (E\w+) (\d+)/ && $2==$ARGV[0];
}
close ($p);

:

$ ./error 10
ECHILD

, .

0
#ifndef NDEBUG
        fprintf(stderr, "Line %d: Error value: %d\n", __LINE__, errno);
#endif

.

-1

. , , , , .

errno.

If the symbol is not known in the implementation below, a general macro is written, for example ERROR_161. If you know the script that generated the code, review its documentation and manually enable possible error codes. This way, you will eventually create a code library. (I agree that this is not very elegant.)

Codes are created by macros and stored as a static array of strings with designated initializers. The size of the array is determined by the largest index.

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

// ... more sys includes as appropriate ...

#define ERRNAME(X) [X] = #X

static const char *errname[] = {
    ERRNAME(E2BIG),
    ERRNAME(EACCES),
    ERRNAME(EADDRINUSE),
    ERRNAME(EADDRNOTAVAIL),
    ERRNAME(EAFNOSUPPORT),
    ERRNAME(EAGAIN),
    // ... more symbols ...
};

const char *errsym(int e)
{
    static char buf[20];

    if (e >= 0 && e < (sizeof(errname) / sizeof(*errname))) {
        if (errname[e]) return errname[e];
    }

    snprintf(buf, sizeof(buf), "ERROR_%u", (unsigned int) e);
    return buf;
}
-1
source

All Articles