Need help to extract function information from c header - ctags

How I can extract the function prototype information form C header? I want my data to in following format.
function_name:return_type:signature
My preference is ctags.

If you are using Universal-ctags(https://ctags.io), following command line is for printing the information in the format:
$ u-ctags --language-force=C -x --_xformat="%N:%{typeref}:%{signature}" --kinds-C=p foo.h
Here is an example:
$ ./ctags --language-force=C -x --_xformat="%N:%{typeref}:%{signature}" --kinds-C=p /usr/include/stdio.h | head
__asprintf:int:(char ** __restrict __ptr,const char * __restrict __fmt,...)
__getdelim:_IO_ssize_t:(char ** __restrict __lineptr,size_t * __restrict __n,int __delimiter,FILE * __restrict __stream)
__isoc99_fscanf:int:(FILE * __restrict __stream,const char * __restrict __format,...)
__isoc99_scanf:int:(const char * __restrict __format,...)
__isoc99_sscanf:int:(const char * __restrict __s,const char * __restrict __format,...)
__isoc99_vfscanf:int:(FILE * __restrict __s,const char * __restrict __format,_G_va_list __arg)
__isoc99_vscanf:int:(const char * __restrict __format,_G_va_list __arg)
__isoc99_vsscanf:int:(const char * __restrict __s,const char * __restrict __format,_G_va_list __arg)
asprintf:int:(char ** __restrict __ptr,const char * __restrict __fmt,...)
clearerr:void:(FILE * __stream)

Related

Linux Proc kernel hello world program

make -C /lib/modules/5.13.0-37-generic/build M=/home/a1085551/osc10e/ch2 modules
make[1]: Entering directory '/usr/src/linux-headers-5.13.0-37-generic'
CC [M] /home/a1085551/osc10e/ch2/hello.o
/home/a1085551/osc10e/ch2/hello.c: In function ‘proc_init’:
/home/a1085551/osc10e/ch2/hello.c:42:41: error: passing argument 4 of ‘proc_create’ from incompatible pointer type [-Werror=incompatible-pointer-types]
42 | proc_create(PROC_NAME, 0, NULL, &proc_ops);
| ^~~~~~~~~
| |
| struct file_operations *
In file included from /home/a1085551/osc10e/ch2/hello.c:16:
./include/linux/proc_fs.h:110:24: note: expected ‘const struct proc_ops *’ but argument is of type ‘struct file_operations *’
110 | struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct proc_ops *proc_ops);
| ^~~~~~~~~~~
/home/a1085551/osc10e/ch2/hello.c: In function ‘proc_read’:
/home/a1085551/osc10e/ch2/hello.c:89:9: warning: ignoring return value of ‘copy_to_user’, declared with attribute warn_unused_result [-Wunused-result]
89 | copy_to_user(usr_buf, buffer, rv);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
make[2]: *** [scripts/Makefile.build:281: /home/a1085551/osc10e/ch2/hello.o] Error 1
make[1]: *** [Makefile:1879: /home/a1085551/osc10e/ch2] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.13.0-37-generic'
make: *** [Makefile:3: all] Error 2
https://github.com/greggagne/osc10e/tree/master/ch2
I try to make the hello kernel module from that link but ended up with this error.
As said in the comments from tsyvarev, in your kernel version "5.13.0-37", the prototype of proc_create() changed. You need to look at the header files of your kernel version. For example, under an Ubuntu distribution, you can find the header file in /usr/src/linux-headers-5.13.0-37-generic/include/linux/proc_fs.h:
$ cat /usr/src/linux-headers-5.13.0-37-generic/include/linux/proc_fs.h
[...]
struct proc_ops {
unsigned int proc_flags;
int (*proc_open)(struct inode *, struct file *);
ssize_t (*proc_read)(struct file *, char __user *, size_t, loff_t *);
ssize_t (*proc_read_iter)(struct kiocb *, struct iov_iter *);
ssize_t (*proc_write)(struct file *, const char __user *, size_t, loff_t *);
/* mandatory unless nonseekable_open() or equivalent is used */
loff_t (*proc_lseek)(struct file *, loff_t, int);
int (*proc_release)(struct inode *, struct file *);
__poll_t (*proc_poll)(struct file *, struct poll_table_struct *);
long (*proc_ioctl)(struct file *, unsigned int, unsigned long);
#ifdef CONFIG_COMPAT
long (*proc_compat_ioctl)(struct file *, unsigned int, unsigned long);
#endif
int (*proc_mmap)(struct file *, struct vm_area_struct *);
unsigned long (*proc_get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
} __randomize_layout;
[...]
struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct proc_ops *proc_ops);
[...]
Hence, you can modify the source code of hello.c as:
/**
* hello.c
*
* Kernel module that communicates with /proc file system.
*
* The makefile must be modified to compile this program.
* Change the line "simple.o" to "hello.o"
*
* Operating System Concepts - 10th Edition
* Copyright John Wiley & Sons - 2018
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#define BUFFER_SIZE 128
#define PROC_NAME "hello"
#define MESSAGE "Hello World\n"
/**
* Function prototypes
*/
static ssize_t proc_read(struct file *file, char *buf, size_t count, loff_t *pos);
static struct proc_ops proc_ops = {
.proc_read = proc_read,
};
/* This function is called when the module is loaded. */
static int proc_init(void)
{
// creates the /proc/hello entry
// the following function call is a wrapper for
// proc_create_data() passing NULL as the last argument
proc_create(PROC_NAME, 0, NULL, &proc_ops);
printk(KERN_INFO "/proc/%s created\n", PROC_NAME);
return 0;
}
/* This function is called when the module is removed. */
static void proc_exit(void) {
// removes the /proc/hello entry
remove_proc_entry(PROC_NAME, NULL);
printk( KERN_INFO "/proc/%s removed\n", PROC_NAME);
}
/**
* This function is called each time the /proc/hello is read.
*
* This function is called repeatedly until it returns 0, so
* there must be logic that ensures it ultimately returns 0
* once it has collected the data that is to go into the
* corresponding /proc file.
*
* params:
*
* file:
* buf: buffer in user space
* count:
* pos:
*/
static ssize_t proc_read(struct file *file, char __user *usr_buf, size_t count, loff_t *pos)
{
int rv = 0;
char buffer[BUFFER_SIZE];
static int completed = 0;
if (completed) {
completed = 0;
return 0;
}
completed = 1;
rv = sprintf(buffer, "Hello World\n");
// copies the contents of buffer to userspace usr_buf
copy_to_user(usr_buf, buffer, rv);
return rv;
}
/* Macros for registering module entry and exit points. */
module_init( proc_init );
module_exit( proc_exit );
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Hello Module");
MODULE_AUTHOR("SGG");
The compilation result is:
$ make
make -C /lib/modules/5.13.0-37-generic/build M=... modules
make[1]: Entering directory '/usr/src/linux-headers-5.13.0-37-generic'
LD [M] /.../hello.ko
BTF [M] /.../hello.ko
Skipping BTF generation for /.../hello.ko due to unavailability of vmlinux
make[1]: Leaving directory '/usr/src/linux-headers-5.13.0-37-generic'
The execution is:
$ sudo insmod hello.ko
$ lsmod | grep hello
hello 16384 0
$ cat /proc/hello
Hello World

Doxygen: Documenting single API that has multiple implementations

Suppose I have one header file with a couple of functions and multiple source files that implement the functions that the header provided.
I would like to document the functions using Doxygen, but only the general comments regarding all implementations, not implementation specific.
What is the best way to see only the header comments? I can't set configuration to ignore all source files as some other source files in the projects don't have headers at all.
For example:
api.h
/**
* #details
* This is general comment for header
*
*********************************************************************/
implemenation1.c
/**
* #details
* This is implementation specific comment for file 1
*
*********************************************************************/
int foo(int a, int b)
{
...
}
implemenation2.c
/**
* #details
* This is implementation specific comment for file 2
*
*********************************************************************/
int foo(int a, int b)
{
...
}
I want to see only that comment on Doxygen:
This is general comment for header
Thanks in advance!
The best solultion I've found so far is this:
api.h
/**
* #details
* This is general comment for header
*
*********************************************************************/
implemenation1.c
/**
* #details
* This is implementation specific comment for file 1
*
* #cond
*********************************************************************/
int foo(int a, int b)
{
...
}
/** #endcond */
implemenation2.c
/**
* #details
* This is implementation specific comment for file 2
*
* #cond
*********************************************************************/
int foo(int a, int b)
{
...
}
/** #endcond */

Theano Import Error-Windows 7-64b

I just installed the Theano.
I have a problem in importing theano in python. When I import Theano in the python 27 32 bit, in Windows 7 64 bit, I get the following errors and warning: I also should add that currently I have installed GCC 4.8.1. What I have to do in order to fix it.
Thanks, Afshin
===============================
00001 #include <Python.h>
00002 #include "structmember.h"
00003 #include <sys/time.h>
00004
00005 // Old Python compatibility from here:
00006 // http://www.python.org/dev/peps/pep-0353/
00007 #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
00008 typedef int Py_ssize_t;
00009 #define PY_SSIZE_T_MAX INT_MAX
00010 #define PY_SSIZE_T_MIN INT_MIN
00011 // This one was taken from:
00012 // http://svn.python.org/projects/python/trunk/Modules/_ctypes/ctypes.h
00013 #define PyNumber_AsSsize_t(ob, exc) PyInt_AsLong(ob)
00014 #endif
00015
00016 #if PY_VERSION_HEX >= 0x03000000
00017 #include "numpy/npy_3kcompat.h"
00018 #define PyCObject_AsVoidPtr NpyCapsule_AsVoidPtr
00019 #define PyCObject_GetDesc NpyCapsule_GetDesc
00020 #define PyCObject_Check NpyCapsule_Check
00021 #endif
00022
00023 #ifndef Py_TYPE
00024 #define Py_TYPE(obj) obj->ob_type
00025 #endif
00026
00027 /**
00028
00029 TODO:
00030 - Check max supported depth of recursion
00031 - CLazyLinker should add context information to errors caught during evaluation. Say what node we were on, add the traceback attached to the node.
00032 - Clear containers of fully-useed intermediate results if allow_gc is 1
00033 - Add timers for profiling
00034 - Add support for profiling space used.
00035
00036
00037 */
00038 static double pytime(const struct timeval * tv)
00039 {
00040 struct timeval t;
00041 if (!tv)
00042 {
00043 tv = &t;
00044 gettimeofday(&t, NULL);
00045 }
00046 return (double) tv->tv_sec + (double) tv->tv_usec / 1000000.0;
00047 }
00048
00049 /**
00050 Helper routine to convert a PyList of integers to a c array of integers.
00051 */
00052 static int unpack_list_of_ssize_t(PyObject * pylist, Py_ssize_t **dst, Py_ssize_t *len,
00053 const char* kwname)
00054 {
00055 Py_ssize_t buflen, *buf;
00056 if (!PyList_Check(pylist))
00057 {
00058 PyErr_Format(PyExc_TypeError, "%s must be list", kwname);
00059 return -1;
00060 }
00061 assert (NULL == *dst);
00062 *len = buflen = PyList_Size(pylist);
00063 *dst = buf = (Py_ssize_t*)calloc(buflen, sizeof(Py_ssize_t));
00064 assert(buf);
00065 for (int ii = 0; ii < buflen; ++ii)
00066 {
00067 PyObject * el_i = PyList_GetItem(pylist, ii);
00068 Py_ssize_t n_i = PyNumber_AsSsize_t(el_i, PyExc_IndexError);
00069 if (PyErr_Occurred())
00070 {
00071 free(buf);
00072 *dst = NULL;
00073 return -1;
00074 }
00075 buf[ii] = n_i;
00076 }
00077 return 0;
00078 }
00079
00080 /**
00081
00082 CLazyLinker
00083
00084
00085 */
00086 typedef struct {
00087 PyObject_HEAD
00088 /* Type-specific fields go here. */
00089 PyObject * nodes; // the python list of nodes
00090 PyObject * thunks; // python list of thunks
00091 PyObject * pre_call_clear; //list of cells to clear on call.
00092 int allow_gc;
00093 Py_ssize_t n_applies;
00094 int n_vars; // number of variables in the graph
00095 int * var_computed; // 1 or 0 for every variable
00096 PyObject ** var_computed_cells;
00097 PyObject ** var_value_cells;
00098 Py_ssize_t **dependencies; // list of vars dependencies for GC
00099 Py_ssize_t *n_dependencies;
00100
00101 Py_ssize_t n_output_vars;
00102 Py_ssize_t * output_vars; // variables that *must* be evaluated by call
00103
00104 int * is_lazy; // 1 or 0 for every thunk
00105
00106 Py_ssize_t * var_owner; // nodes[[var_owner[var_idx]]] is var[var_idx]->owner
00107 int * var_has_owner; // 1 or 0
00108
00109 Py_ssize_t * node_n_inputs;
00110 Py_ssize_t * node_n_outputs;
00111 Py_ssize_t ** node_inputs;
00112 Py_ssize_t ** node_outputs;
00113 Py_ssize_t * node_inputs_outputs_base; // node_inputs and node_outputs point into this
00114 Py_ssize_t * node_n_prereqs;
00115 Py_ssize_t ** node_prereqs;
00116
00117 Py_ssize_t * update_storage; // input cells to update with the last outputs in output_vars
00118 Py_ssize_t n_updates;
00119
00120 void ** thunk_cptr_fn;
00121 void ** thunk_cptr_data;
00122 PyObject * call_times;
00123 PyObject * call_counts;
00124 int do_timing;
00125 int need_update_inputs;
00126 int position_of_error; // -1 for no error, otw the index into `thunks` that failed.
00127 } CLazyLinker;
00128
00129
00130 static void
00131 CLazyLinker_dealloc(PyObject* _self)
00132 {
00133 CLazyLinker* self = (CLazyLinker *) _self;
00134 free(self->thunk_cptr_fn);
00135 free(self->thunk_cptr_data);
00136
00137 free(self->is_lazy);
00138
00139 free(self->update_storage);
00140
00141 if (self->node_n_prereqs)
00142 {
00143 for (int i = 0; i < self->n_applies; ++i)
00144 {
00145 free(self->node_prereqs[i]);
00146 }
00147 }
00148 free(self->node_n_prereqs);
00149 free(self->node_prereqs);
00150 free(self->node_inputs_outputs_base);
00151 free(self->node_n_inputs);
00152 free(self->node_n_outputs);
00153 free(self->node_inputs);
00154 free(self->node_outputs);
00155
00156 if (self->dependencies)
00157 {
00158 for (int i = 0; i < self->n_vars; ++i)
00159 {
00160 free(self->dependencies[i]);
00161 }
00162 free(self->dependencies);
00163 free(self->n_dependencies);
00164 }
00165
00166 free(self->var_owner);
00167 free(self->var_has_owner);
00168 free(self->var_computed);
00169 if (self->var_computed_cells)
00170 {
00171 for (int i = 0; i < self->n_vars; ++i)
00172 {
00173 Py_DECREF(self->var_computed_cells[i]);
00174 Py_DECREF(self->var_value_cells[i]);
00175 }
00176 }
00177 free(self->var_computed_cells);
00178 free(self->var_value_cells);
00179 free(self->output_vars);
00180
00181 Py_XDECREF(self->nodes);
00182 Py_XDECREF(self->thunks);
00183 Py_XDECREF(self->call_times);
00184 Py_XDECREF(self->call_counts);
00185 Py_XDECREF(self->pre_call_clear);
00186 Py_TYPE(self)->tp_free((PyObject*)self);
00187 }
00188 static PyObject *
00189 CLazyLinker_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
00190 {
00191 CLazyLinker *self;
00192
00193 self = (CLazyLinker *)type->tp_alloc(type, 0);
00194 if (self != NULL) {
00195 self->nodes = NULL;
00196 self->thunks = NULL;
00197 self->pre_call_clear = NULL;
00198
00199 self->allow_gc = 1;
00200 self->n_applies = 0;
00201 self->n_vars = 0;
00202 self->var_computed = NULL;
00203 self->var_computed_cells = NULL;
00204 self->var_value_cells = NULL;
00205 self->dependencies = NULL;
00206 self->n_dependencies = NULL;
00207
00208 self->n_output_vars = 0;
00209 self->output_vars = NULL;
00210
00211 self->is_lazy = NULL;
00212
......
(I just removed some codes, because Stachoverflow does not allow more than 30000 character......
......
01075 PyModule_AddObject(m, "CLazyLinker", (PyObject *)&lazylinker_ext_CLazyLinkerType);
01076
01077 return RETVAL;
01078 }
01079
01080
Problem occurred during compilation with the command line below:
C:\cygwin64\bin\g++.exe -shared -g -march=nehalem -mmmx -mno-3dnow -msse -msse2 -msse3 -mssse3 -mno-sse4a -mcx16 -msahf -mno-movbe -mno-aes -mno-sha -mno-pclmul -mpopcnt -mno-abm -mno-lwp -mno-fma -mno-fma4 -mno-xop -mno-bmi -mno-bmi2 -mno-tbm -mno-avx -mno-avx2 -msse4.2 -msse4.1 -mno-lzcnt -mno-rtm -mno-hle -mno-rdrnd -mno-f16c -mno-fsgsbase -mno-rdseed -mno-prfchw -mno-adx -mfxsr -mno-xsave -mno-xsaveopt -mno-avx512f -mno-avx512er -mno-avx512cd -mno-avx512pf -mno-prefetchwt1 --param l1-cache-size=32 --param l1-cache-line-size=64 --param l2-cache-size=6144 -mtune=nehalem -D NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION -m32 -IC:\python2732\lib\site-packages\numpy-1.9.0-py2.7-win32.egg\numpy\core\include -IC:\python2732\include -o C:\Users\Dell\AppData\Local\Theano\compiledir_Windows-7-6.1.7601-SP1-Intel64_Family_6_Model_30_Stepping_5_GenuineIntel-2.7.8-32\lazylinker_ext\lazylinker_ext.pyd C:\Users\Dell\AppData\Local\Theano\compiledir_Windows-7-6.1.7601-SP1-Intel64_Family_6_Model_30_Stepping_5_GenuineIntel-2.7.8-32\lazylinker_ext\mod.cpp -LC:\python2732\libs -LC:\python2732 -lpython27
===============================
In file included from C:\python2732\include/Python.h:86:0,
from C:\Users\Dell\AppData\Local\Theano\compiledir_Windows-7-6.1.7601-SP1-Intel64_Family_6_Model_30_Stepping_5_GenuineIntel-2.7.8-32\lazylinker_ext\mod.cpp:1:
C:\python2732\include/intobject.h:46:35: error: expected initializer before 'PyInt_AsUnsignedLongLongMask'
PyAPI_FUNC(unsigned PY_LONG_LONG) PyInt_AsUnsignedLongLongMask(PyObject *);
^
In file included from C:\python2732\include/Python.h:8:0,
from C:\Users\Dell\AppData\Local\Theano\compiledir_Windows-7-6.1.7601-SP1-Intel64_Family_6_Model_30_Stepping_5_GenuineIntel-2.7.8-32\lazylinker_ext\mod.cpp:1:
C:\python2732\include/pyconfig.h:302:23: error: '__int64' was not declared in this scope
# define PY_LONG_LONG __int64
^
C:\python2732\include/longobject.h:50:44: note: in expansion of macro 'PY_LONG_LONG'
PyAPI_FUNC(PyObject *) PyLong_FromLongLong(PY_LONG_LONG);
^
In file included from C:\python2732\include/Python.h:58:0,
from C:\Users\Dell\AppData\Local\Theano\compiledir_Windows-7-6.1.7601-SP1-Intel64_Family_6_Model_30_Stepping_5_GenuineIntel-2.7.8-32\lazylinker_ext\mod.cpp:1:
C:\python2732\include/pyconfig.h:302:23: error: '__int64' does not name a type
# define PY_LONG_LONG __int64
^
C:\python2732\include/pyport.h:793:34: note: in definition of macro 'PyAPI_FUNC'
# define PyAPI_FUNC(RTYPE) RTYPE
^
C:\python2732\include/longobject.h:52:12: note: in expansion of macro 'PY_LONG_LONG'
PyAPI_FUNC(PY_LONG_LONG) PyLong_AsLongLong(PyObject *);
^
In file included from C:\python2732\include/Python.h:88:0,
from C:\Users\Dell\AppData\Local\Theano\compiledir_Windows-7-6.1.7601-SP1-Intel64_Family_6_Model_30_Stepping_5_GenuineIntel-2.7.8-32\lazylinker_ext\mod.cpp:1:
C:\python2732\include/longobject.h:53:35: error: expected initializer before 'PyLong_AsUnsignedLongLong'
PyAPI_FUNC(unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLong(PyObject *);
^
C:\python2732\include/longobject.h:54:35: error: expected initializer before 'PyLong_AsUnsignedLongLongMask'
PyAPI_FUNC(unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLongMask(PyObject *);
^
In file included from C:\python2732\include/Python.h:58:0,
from C:\Users\Dell\AppData\Local\Theano\compiledir_Windows-7-6.1.7601-SP1-Intel64_Family_6_Model_30_Stepping_5_GenuineIntel-2.7.8-32\lazylinker_ext\mod.cpp:1:
C:\python2732\include/pyconfig.h:302:23: error: '__int64' does not name a type
# define PY_LONG_LONG __int64
^
C:\python2732\include/pyport.h:793:34: note: in definition of macro 'PyAPI_FUNC'
# define PyAPI_FUNC(RTYPE) RTYPE
^
C:\python2732\include/longobject.h:55:12: note: in expansion of macro 'PY_LONG_LONG'
PyAPI_FUNC(PY_LONG_LONG) PyLong_AsLongLongAndOverflow(PyObject *, int *);
^
Traceback (most recent call last):
File "C:\Users\Dell\Documents\Pyton\Home Work 1\test-theano\test-theano.py", line 7, in <module>
from theano import *
File "C:\python2732\lib\site-packages\theano-0.7.0-py2.7.egg\theano\__init__.py", line 55, in <module>
from theano.compile import \
File "C:\python2732\lib\site-packages\theano-0.7.0-py2.7.egg\theano\compile\__init__.py", line 9, in <module>
from theano.compile.function_module import *
File "C:\python2732\lib\site-packages\theano-0.7.0-py2.7.egg\theano\compile\function_module.py", line 18, in <module>
import theano.compile.mode
File "C:\python2732\lib\site-packages\theano-0.7.0-py2.7.egg\theano\compile\mode.py", line 11, in <module>
import theano.gof.vm
File "C:\python2732\lib\site-packages\theano-0.7.0-py2.7.egg\theano\gof\vm.py", line 568, in <module>
import lazylinker_c
File "C:\python2732\lib\site-packages\theano-0.7.0-py2.7.egg\theano\gof\lazylinker_c.py", line 116, in <module>
preargs=args)
File "C:\python2732\lib\site-packages\theano-0.7.0-py2.7.egg\theano\gof\cmodule.py", line 2010, in compile_str
(status, compile_stderr.replace('\n', '. ')))
Exception: Compilation failed (return status=1): In file included from C:\python2732\include/Python.h:86:0,. from C:\Users\Dell\AppData\Local\Theano\compiledir_Windows-7-6.1.7601-SP1-Intel64_Family_6_Model_30_Stepping_5_GenuineIntel-2.7.8-32\lazylinker_ext\mod.cpp:1:. C:\python2732\include/intobject.h:46:35: error: expected initializer before 'PyInt_AsUnsignedLongLongMask'. PyAPI_FUNC(unsigned PY_LONG_LONG) PyInt_AsUnsignedLongLongMask(PyObject *);. ^. In file included from C:\python2732\include/Python.h:8:0,. from C:\Users\Dell\AppData\Local\Theano\compiledir_Windows-7-6.1.7601-SP1-Intel64_Family_6_Model_30_Stepping_5_GenuineIntel-2.7.8-32\lazylinker_ext\mod.cpp:1:. C:\python2732\include/pyconfig.h:302:23: error: '__int64' was not declared in this scope. # define PY_LONG_LONG __int64. ^. C:\python2732\include/longobject.h:50:44: note: in expansion of macro 'PY_LONG_LONG'. PyAPI_FUNC(PyObject *) PyLong_FromLongLong(PY_LONG_LONG);. ^. In file included from C:\python2732\include/Python.h:58:0,. from C:\Users\Dell\AppData\Local\Theano\compiledir_Windows-7-6.1.7601-SP1-Intel64_Family_6_Model_30_Stepping_5_GenuineIntel-2.7.8-32\lazylinker_ext\mod.cpp:1:. C:\python2732\include/pyconfig.h:302:23: error: '__int64' does not name a type. # define PY_LONG_LONG __int64. ^. C:\python2732\include/pyport.h:793:34: note: in definition of macro 'PyAPI_FUNC'. # define PyAPI_FUNC(RTYPE) RTYPE. ^. C:\python2732\include/longobject.h:52:12: note: in expansion of macro 'PY_LONG_LONG'. PyAPI_FUNC(PY_LONG_LONG) PyLong_AsLongLong(PyObject *);. ^. In file included from C:\python2732\include/Python.h:88:0,. from C:\Users\Dell\AppData\Local\Theano\compiledir_Windows-7-6.1.7601-SP1-Intel64_Family_6_Model_30_Stepping_5_GenuineIntel-2.7.8-32\lazylinker_ext\mod.cpp:1:. C:\python2732\include/longobject.h:53:35: error: expected initializer before 'PyLong_AsUnsignedLongLong'. PyAPI_FUNC(unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLong(PyObject *);. ^. C:\python2732\include/longobject.h:54:35: error: expected initializer before 'PyLong_AsUnsignedLongLongMask'. PyAPI_FUNC(unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLongMask(PyObject *);. ^. In file included from C:\python2732\include/Python.h:58:0,. from C:\Users\Dell\AppData\Local\Theano\compiledir_Windows-7-6.1.7601-SP1-Intel64_Family_6_Model_30_Stepping_5_GenuineIntel-2.7.8-32\lazylinker_ext\mod.cpp:1:. C:\python2732\include/pyconfig.h:302:23: error: '__int64' does not name a type. # define PY_LONG_LONG __int64. ^. C:\python2732\include/pyport.h:793:34: note: in definition of macro 'PyAPI_FUNC'. # define PyAPI_FUNC(RTYPE) RTYPE. ^. C:\python2732\include/longobject.h:55:12: note: in expansion of macro 'PY_LONG_LONG'. PyAPI_FUNC(PY_LONG_LONG) PyLong_AsLongLongAndOverflow(PyObject *, int *);. ^.
This was also discussed on the Theano mailing list. For the benefit of StackOverflow users, the answer was to install and use MinGW in preference to Cygwin.
If both are installed, MinGW should be before Cygwin in the PATH.

"struct has no member named" error with gcc on dev machine

#include <stdio.h>
#include <stdlib.h>
#include "ReadMethods.h"
int main(int argc,char * argv[])
{
DPDA WordChecker;
DPDA * WordCheckerPointer=&WordChecker;
WordChecker.DPDAFilename=(char*)malloc(25*sizeof(char));
WordChecker.DPDAInputFilename=(char*)malloc(25*sizeof(char));
WordChecker.DPDAOutputFilename=(char*)malloc(25*sizeof(char));
strcpy( WordChecker.DPDAFilename,argv[1]);
strcpy( WordChecker.DPDAInputFilename,argv[2]);
strcpy( WordChecker.DPDAOutputFilename,argv[3]);
readDPDA(argv[1],WordCheckerPointer);
readInputLines(argv[2],WordCheckerPointer,argv[3]);
return 0;
}
This is my code that gives error from mallocs until last strcpy() ,total 6 lines.The error is "DPDA has no member named DPDAFilename" and same for other fields for every malloc and strcpy linesthat i work on.Here is the part of header file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tagRule{
char *startingState;
char symbolToPop;
char expectedInput;
char *endingState;
char symbolToPush;
}Rule;
typedef struct tagStackDPDA{
char * arrayOfSymbols;
int stackElementCount;
char * currentState;
}stackDPDA;
typedef struct tagDPDA{
char * alphabet;
char * stackSymbols;
char ** states;
char *startingState;
char **finalStates;
int finalStatesAmount;
Rule * ruleList;
stackDPDA stackOfDPDA;
int sizeArray[4];//This array holds amount values of states,alphabet symbols,stack symbols and transition rules
char *DPDAFilename;
char *DPDAInputFilename;
char *DPDAOutputFilename;
}DPDA;
The code works fine in codeblocks environment but in gcc (-Wall -ansi).Those filenames come from input text files yet i am not sure it can cause this error.
Edit:By the way I am using this command line to compile;
gcc -Wall -ansi main.c ReadMethods.h -o WordChecker
May be if you compile in C mode, you have to use C-style comments in header?
/**/ instead of //

Symbolic errno to String

Is there a command-line tool that will take a symbolic errno such as EINVAL and print the corresponding string, Invalid argument?
I would like to avoid having to find that EINVAL is value 22 on my system and then using$ perror 22.
Ideally I could write something like
$ errorcommand EINVAL
Invalid argument
$
AFAIK, there isn't a standard tool that does the job. At one level, it wouldn't be particularly hard to write one - the messiest parts are finding the correct file to parse (is is often, but by no means always, /usr/include/sys/errno.h) and then taking the data from that to do the mapping of names to numbers. I have not found a system that uses enum values rather than #define values, but it is probably only a matter of time. It is also a moot point whether to generate a triple consisting of token number (EINTR, etc), token name ("EINTR", etc) and error message ("Interrupted system call", etc), or whether to use just the number and name and leave it to 'strerror()' to supply the message.
As I said, it isn't particularly hard. I already had a program called 'errno' that accepted pure numeric values and printed the corresponding error messages:
$ errno 1:10 20
1: Operation not permitted
2: No such file or directory
3: No such process
4: Interrupted system call
5: Input/output error
6: Device not configured
7: Argument list too long
8: Exec format error
9: Bad file descriptor
10: No child processes
20: Not a directory
$
I've written a Perl script and hacked the program to handle symbolic error numbers too:
$ errno 1:4 EINTR ENOTDIR
1 (EPERM): Operation not permitted
2 (ENOENT): No such file or directory
3 (ESRCH): No such process
4 (EINTR): Interrupted system call
EINTR (4): Interrupted system call
ENOTDIR (20): Not a directory
$
It does not handle ranges of symbolic error numbers (exercise for the reader).
generrno.pl
#!/usr/bin/perl -w
#
# #(#)$Id: generrno.pl,v 1.1 2010/02/07 18:39:18 jleffler Exp jleffler $
#
# Generate table of error number constants from given file(s)
use strict;
my %symlist;
my $maxsymlen = 0;
my $maxmsglen = 0;
while (<>)
{
next unless m%^\s*#\s*define\s+(E[A-Z0-9a-z]+)\s+(\d+)\s*/\*\s*([A-Za-z].*\S)\s*\*/%;
$symlist{$1} = { number => $2, message => $3 };
$maxsymlen = length($1) if length($1) > $maxsymlen;
$maxmsglen = length($3) if length($3) > $maxmsglen;
}
my $format = sprintf " { %%-%ds %%-%ds %%-5s %%-%ds },\n", $maxsymlen + 3, $maxsymlen + 1, $maxmsglen + 2;
foreach my $key (sort keys %symlist)
{
my $name = qq{"$key",};
my $symbol = qq{$key,};
my $number = qq{$symlist{$key}->{number},};
my $message = qq{"$symlist{$key}->{message}"};
printf $format, $name, $symbol, $number, $message;
}
errno.c
/*
#(#)File: $RCSfile: errno.c,v $
#(#)Version: $Revision: 2.2 $
#(#)Last changed: $Date: 2010/02/07 19:22:37 $
#(#)Purpose: Print messages corresponding to errno values or name
#(#)Author: J Leffler
#(#)Copyright: (C) JLSS 2003,2005,2008,2010
*/
/*TABSTOP=4*/
#define MAIN_PROGRAM
/* Need O/S specific messages as well as POSIX messages */
//#if __STDC_VERSION__ >= 199901L
//#define _XOPEN_SOURCE 600
//#else
//#define _XOPEN_SOURCE 500
//#endif /* __STDC_VERSION__ */
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /* getopt() on MacOS X 10.2 */
#include "stderr.h"
#include "range.h"
typedef struct err_info
{
const char *errsym; /* Error symbol - "EINTR" */
int errnum; /* Error number - EINTR */
int errdef; /* Error define - 4 */
const char *errmsg; /* Error message - Interrupted system call */
} err_info;
/*
** Generate generrno.h using:
** perl generrno.pl /usr/include/sys/errno.h > generrno.h
** NB: list must be sorted alphabetically on symbol name
*/
static const err_info err_msgs[] =
{
#include "generrno.h"
};
static const char usestr[] = "[-qV] [--] lo[:hi] ...";
#define DIM(x) (sizeof(x)/sizeof(*(x)))
static const err_info *err_nums[DIM(err_msgs)];
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
const char jlss_id_errno_c[] = "#(#)$Id: errno.c,v 2.2 2010/02/07 19:22:37 jleffler Exp $";
#endif /* lint */
static int cmp_err_number(const void *v1, const void *v2)
{
int e1 = (*((const err_info * const *)v1))->errnum;
int e2 = (*((const err_info * const *)v2))->errnum;
return(e1 - e2);
}
static void map_numbers(void)
{
int i;
for (i = 0; i < DIM(err_msgs); i++)
err_nums[i] = &err_msgs[i];
qsort(err_nums, DIM(err_nums), sizeof(*err_nums), cmp_err_number);
}
static const char *err_symbol(int num)
{
const char *sym = "<UNKNOWN>";
err_info lookfor = { 0, num, 0, 0 };
err_info *lookptr = &lookfor;
const err_info **found = bsearch(&lookptr, err_nums, DIM(err_nums), sizeof(*err_nums), cmp_err_number);
if (found != 0)
sym = (*found)->errsym;
return(sym);
}
static int cmp_err_symbol(const void *v1, const void *v2)
{
const char *s1 = ((const err_info *)v1)->errsym;
const char *s2 = ((const err_info *)v2)->errsym;
return(strcmp(s1, s2));
}
static int pr_string_errno(const char *arg, int qflag)
{
int estat = EXIT_SUCCESS;
err_info lookfor = { arg, 0, 0, 0 };
const err_info *found = bsearch(&lookfor, err_msgs, DIM(err_msgs), sizeof(*err_msgs), cmp_err_symbol);
if (found == 0)
{
err_remark("unrecognized symbol %s\n", arg);
estat = EXIT_FAILURE;
}
else if (qflag == 0)
printf("%s (%d): %s\n", arg, found->errnum, found->errmsg);
return(estat);
}
static int pr_number_errno(const char *arg, int qflag)
{
int estat = EXIT_SUCCESS;
long lo;
long hi;
const char *endp;
long msg;
endp = numeric_range(arg, &lo, &hi);
if (endp == arg)
err_remark("Invalid range specified (%s) - should be lo[:hi]\n", arg);
else if (*endp != '\0')
err_remark("Non-numeric character (%c) after range '%s'\n",
(isprint((unsigned char)*endp) ? *endp : '?'), arg);
else
{
for (msg = lo; msg <= hi; msg++)
{
char *msgtxt = strerror(msg);
if (msgtxt == 0)
{
err_remark("no message for errno = %ld\n", msg);
estat = EXIT_FAILURE;
}
else if (qflag == 0)
printf("%ld (%s): %s\n", msg, err_symbol(msg), msgtxt);
}
}
return(estat);
}
static int pr_errno(char *arg, int qflag)
{
int estat;
if (isalpha(*arg))
estat = pr_string_errno(arg, qflag);
else
estat = pr_number_errno(arg, qflag);
return(estat);
}
int main(int argc, char **argv)
{
int i;
int opt;
int nstat;
int estat = EXIT_SUCCESS;
int qflag = 0;
int nflag = 0;
err_setarg0(argv[0]);
map_numbers();
while ((opt = getopt(argc, argv, "qV0:1:2:3:4:5:6:7:8:9:")) != EOF)
{
switch (opt)
{
case 'q':
qflag = 1;
break;
case 'V':
err_version("ERRNO", "$Revision: 2.2 $ ($Date: 2010/02/07 19:22:37 $)");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
/* GETOPT() is probably not the right tool for this job! */
nstat = pr_errno(optarg-2, qflag);
if (estat == EXIT_SUCCESS)
estat = nstat;
nflag = 1;
break;
default:
err_usage(usestr);
break;
}
}
if (optind >= argc && nflag == 0)
err_usage(usestr);
for (i = optind; i < argc; i++)
{
nstat = pr_errno(argv[i], qflag);
if (estat == EXIT_SUCCESS)
estat = nstat;
}
return(estat);
}
The code needs some supporting files - stderr.h, range.h, range2.c and stderrmin.c (a simpler version of the stderr.c I normally use, which has extra bells and whistles for handling syslog and writing to file descriptors instead of file pointers.).
stderr.h
/*
#(#)File: $RCSfile: stderr.h,v $
#(#)Version: $Revision: 9.2 $
#(#)Last changed: $Date: 2009/03/06 06:52:26 $
#(#)Purpose: Header file for standard error functions
#(#)Author: J Leffler
#(#)Copyright: (C) JLSS 1989-93,1996-99,2003,2005-09
#(#)Product: :PRODUCT:
*/
#ifndef STDERR_H
#define STDERR_H
#ifdef MAIN_PROGRAM
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
const char jlss_id_stderr_h[] = "#(#)$Id: stderr.h,v 9.2 2009/03/06 06:52:26 jleffler Exp $";
#endif /* lint */
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
#include <stdarg.h>
#ifdef __GNUC__
#define PRINTFLIKE(n,m) __attribute__((format(printf,n,m)))
#define NORETURN() __attribute__((noreturn))
#else
#define PRINTFLIKE(n,m) /* If only */
#define NORETURN() /* If only */
#endif /* __GNUC__ */
/* -- Definitions for error handling */
enum { ERR_STAT = 1 }; /* Default exit status */
enum { ERR_DEFAULT = 0x0000 }; /* Default flag */
enum { ERR_NOFLUSH = 0x0001 }; /* Do not flush open files */
enum { ERR_EXIT = 0x0004 }; /* Exit -- do not return */
enum { ERR_ABORT = 0x0008 }; /* Abort -- do not return */
enum { ERR_STAMP = 0x0020 }; /* Timestamp messages */
enum { ERR_NOARG0 = 0x0040 }; /* Do not print arg0 prefix */
enum { ERR_PID = 0x0080 }; /* Include pid=nnnnn info */
enum { ERR_ERRNO = 0x0100 }; /* Include system error */
#ifdef USE_STDERR_SYSLOG
/* Definitions related to using syslog */
enum { ERR_LOG_EMERG = 0x01000 }; /* system is unusable */
enum { ERR_LOG_ALERT = 0x02000 }; /* action must be taken immediately */
enum { ERR_LOG_CRIT = 0x04000 }; /* critical conditions */
enum { ERR_LOG_ERR = 0x08000 }; /* error conditions */
enum { ERR_LOG_WARNING = 0x10000 }; /* warning conditions */
enum { ERR_LOG_NOTICE = 0x20000 }; /* normal but signification condition */
enum { ERR_LOG_INFO = 0x40000 }; /* informational */
enum { ERR_LOG_DEBUG = 0x80000 }; /* debug-level messages */
enum { ERR_LOG_LEVEL_HI = ERR_LOG_EMERG|ERR_LOG_ALERT|ERR_LOG_CRIT|ERR_LOG_ERR };
enum { ERR_LOG_LEVEL_LO = ERR_LOG_WARNING|ERR_LOG_NOTICE|ERR_LOG_INFO|ERR_LOG_DEBUG };
enum { ERR_LOG_LEVEL = ERR_LOG_LEVEL_HI|ERR_LOG_LEVEL_LO };
#endif /* USE_STDERR_SYSLOG */
/* -- Standard combinations of flags */
enum { ERR_REM = ERR_DEFAULT };
enum { ERR_ERR = ERR_EXIT };
enum { ERR_ABT = ERR_ABORT };
enum { ERR_LOG = ERR_STAMP|ERR_PID };
enum { ERR_SYSREM = ERR_REM|ERR_ERRNO };
enum { ERR_SYSERR = ERR_ERR|ERR_ERRNO };
/* -- Maximum recorded length of argv[0]; extra is truncated */
enum { ERR_MAXLEN_ARGV0 = 63 };
/* -- Global definitions */
extern const char err_format1[]; /* "%s\n" - for one string argument */
extern const char err_format2[]; /* "%s %s\n" - for two string arguments */
extern const char *err_getarg0(void);
extern void err_setarg0(const char *argv0);
extern FILE *err_stderr(FILE *fp);
extern const char *err_rcs_string(const char *s, char *buffer, size_t buflen);
extern void err_abort(const char *format, ...) PRINTFLIKE(1,2) NORETURN();
extern void err_error(const char *format, ...) PRINTFLIKE(1,2) NORETURN();
extern void err_error1(const char *s1) NORETURN();
extern void err_error2(const char *s1, const char *s2) NORETURN();
extern void err_help(const char *use_str, const char *hlp_str) NORETURN();
extern void err_helplist(const char *use_str, const char * const *help_list) NORETURN();
extern void err_internal(const char *function, const char *msg) NORETURN();
extern void err_logmsg(FILE *fp, int flags, int estat, const char *format, ...) PRINTFLIKE(4,5);
extern void err_print(int flags, int estat, const char *format, va_list args);
extern void err_printversion(const char *program, const char *verinfo);
extern void err_remark(const char *format, ...) PRINTFLIKE(1,2);
extern void err_remark1(const char *s1);
extern void err_remark2(const char *s1, const char *s2);
extern void err_report(int flags, int estat, const char *format, ...) PRINTFLIKE(3,4);
extern void err_syserr(const char *format, ...) PRINTFLIKE(1,2) NORETURN();
extern void err_syserr1(const char *s1) NORETURN();
extern void err_syserr2(const char *s1, const char *s2) NORETURN();
extern void err_sysrem(const char *format, ...) PRINTFLIKE(1,2);
extern void err_sysrem1(const char *s1);
extern void err_sysrem2(const char *s1, const char *s2);
extern void err_usage(const char *usestr) NORETURN();
extern void err_version(const char *program, const char *verinfo) NORETURN();
extern int err_getlogopts(void); /* Get default log options */
extern int err_setlogopts(int new_opts); /* Set default log options */
#ifdef USE_STDERR_FILEDESC
extern int err_use_fd(int fd); /* Use file descriptor */
#endif /* USE_STDERR_FILEDESC */
#ifdef USE_STDERR_SYSLOG
/* In case of doubt, use zero for both logopts and facility */
extern int err_use_syslog(int logopts, int facility); /* Configure/use syslog() */
#endif /* USE_STDERR_SYSLOG */
/*
** JL 2003-07-31: Security Note.
** Question: given that err_remark("abc\n") and err_remark1("abc")
** produce the same output, when should you use err_remark1()
** instead of err_remark()?
** Answer 1: trivia - when you can't put the newline in the string.
** Answer 2: security - when the argument contains user input and could,
** therefore, contain conversion specifiers, etc. The code in
** err_remark() does not (and cannot) verify that you have
** passed correct arguments for the conversion specifiers in
** the format string.
** Answer 3: inertia - when migrating code that uses remark().
**
** Generalizing: when you use a function that has 'const char *format'
** in the prototype above, make sure your code is fully in charge of the
** format string to avoid security lapses. Do not allow the user to
** provide that string unless you stringently check it beforehand.
*/
#endif /* STDERR_H */
range.h
/*
#(#)File: $RCSfile: range.h,v $
#(#)Version: $Revision: 1.8 $
#(#)Last changed: $Date: 2008/02/11 07:39:36 $
#(#)Purpose: Declaration of range parsing functions
#(#)Author: J Leffler
#(#)Copyright: (C) JLSS 1997,2005,2007-08
#(#)Product: :PRODUCT:
*/
/*TABSTOP=4*/
#ifndef RANGE_H
#define RANGE_H
#ifdef MAIN_PROGRAM
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
const char jlss_id_range_h[] = "#(#)$Id: range.h,v 1.8 2008/02/11 07:39:36 jleffler Exp $";
#endif /* lint */
#endif /* MAIN_PROGRAM */
/*
** parse_range(): parse range of non-negative numbers.
**
** Given a string, parse_range() returns the lo and hi values corresponding
** to the range specified by the string. For example:
** Input: Low High
** 23 23 23
** 23-25 23 25
** 23- 23 0
** -23 0 23
** Any delimiter other than '-' before or after a number terminates the
** scan, but commas are skipped. Returns pointer to character after
** last character parsed (which may or may not be '\0') if successful.
** Otherwise, returns null.
**
** Idiomatic use:
**
** const char *ptr = source_string;
** const char *nxt;
** while ((nxt = parse_range(ptr, &lo, &hi)) != 0)
** {
** if (nxt == ptr)
** err_error("invalid range string (%s)\n", source_string);
** use_range(lo, hi);
** ptr = nxt;
** }
*/
extern const char *parse_range(const char *str, long *lo, long *hi);
/*
** numeric_range(): parse range of numbers, positive or negative.
**
** Input: Low High
** 23 23 23
** -23 -23 -23
** 23:25 23 25
** 23..25 23 25
** -23..-25 -25 -23
** -23..25 -23 25
** 23..-25 -25 23
** Returns pointer to '\0' at end of string if OK, sets *lo and *hi,
** and guarantees *lo <= *hi.
** Otherwise, returns pointer to start of string and does not set *lo or *hi.
**
** Idiomatic use:
**
** const char *ptr = source_string;
** const char *nxt;
** while ((nxt = numeric_range(ptr, &lo, &hi)) != 0)
** {
** if (nxt == ptr)
** err_error("invalid range string (%s)\n", source_string);
** use_range(lo, hi);
** ptr = nxt;
** }
*/
extern const char *numeric_range(const char *str, long *lo, long *hi);
#endif /* RANGE_H */
range2.c
/*
#(#)File: $RCSfile: range2.c,v $
#(#)Version: $Revision: 1.8 $
#(#)Last changed: $Date: 2008/02/11 08:44:50 $
#(#)Purpose: Decode string into range of integers.
#(#)Author: J Leffler
#(#)Copyright: (C) JLSS 1997,2002,2005,2007-08
#(#)Product: :PRODUCT:
*/
/*TABSTOP=4*/
/*
** Parse number ranges, dealing with positive and negative values,
** and ranges separated by either colon or double-dot.
**
** Input: Low High
** 23 23 23
** -23 -23 -23
** 23:25 23 25
** 23..25 23 25
** -23..-25 -25 -23
** -23..25 -23 25
** 23..-25 -25 23
** -23..+25 -23 25
** Any other delimiter after number (or before number) terminates
** input. NB: a leading colon (or dot) is not a valid range. If
** there is a format error, the returned pointer points to the
** start of the string (and lo and hi are unchanged). If there is
** no error, then the returned pointer points to the ASCII NUL at
** the end of the string.
*/
#include "range.h"
#include <stdlib.h>
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
const char jlss_id_range2_c[] = "#(#)$Id: range2.c,v 1.8 2008/02/11 08:44:50 jleffler Exp $";
#endif /* lint */
/*
** Parse numeric range.
** Return pointer to trailing '\0' if OK, else pointer to input string
*/
const char *numeric_range(const char *str, long *lo, long *hi)
{
const char *s = str;
char *t;
long l;
long h;
l = strtol(s, &t, 10);
if (*t == '\0')
{
/* Just one number */
*lo = *hi = l;
return(t);
}
if (*t == ':')
t += 1;
else if (t[0] == '.' && t[1] == '.')
t += 2;
else
{
/* Format error */
return(str);
}
h = strtol(t, &t, 10);
if (*t != '\0')
{
/* Format error */
return(str);
}
if (h < l)
{
long x = h;
h = l;
l = x;
}
*lo = l;
*hi = h;
return(t);
}
#ifdef TEST
#include <stdio.h>
#include "stderr.h"
int main(int argc, char **argv)
{
int i;
long lo;
long hi;
const char *t;
const char *s;
err_setarg0(argv[0]);
if (argc <= 1)
err_usage("range [...]");
for (i = 1; i < argc; i++)
{
t = argv[i];
if (t != 0 && *t != '\0')
{
printf("Parse: %15s (addr = 0x%08lX) ", t, (unsigned long)t);
fflush(stdout);
s = numeric_range(t, &lo, &hi);
printf("Range: %2ld -> %2ld (addr = 0x%08lX; trailer = <<%s>>)\n", lo, hi, (unsigned long)s, s);
fflush(stdout);
}
}
return(0);
}
#endif /* TEST */
stderrmin.c
This is about 400 lines, instead of about 700 lines. Yes, it is overkill for this program; I don't use it only in this program.
/*
#(#)File: $RCSfile: stderrmin.c,v $
#(#)Version: $Revision: 9.6 $
#(#)Last changed: $Date: 2009/03/02 20:27:38 $
#(#)Purpose: Minimal implementation of error reporting routines
#(#)Author: J Leffler
#(#)Copyright: (C) JLSS 1988-91,1996-99,2001,2003,2005-09
#(#)Product: :PRODUCT:
*/
/*TABSTOP=4*/
#undef STDERR_EXTENDED
#include "stderr.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#else
extern int getpid(void);
#endif /* HAVE_UNISTD_H */
enum { MAX_MSGLEN = 2048 };
/* Global format strings */
const char err_format1[] = "%s\n";
const char err_format2[] = "%s %s\n";
static const char def_format[] = "%Y-%m-%d %H:%M:%S";
static const char *tm_format = def_format;
static char arg0[ERR_MAXLEN_ARGV0+1] = "**undefined**";
/* Permitted default error flags */
enum { ERR_LOGOPTS = ERR_NOFLUSH | ERR_EXIT | ERR_ABORT | ERR_STAMP |
ERR_NOARG0 | ERR_PID | ERR_ERRNO };
static int err_flags = 0; /* Default error flags (ERR_STAMP, ERR_PID, etc) */
static FILE *errout = 0;
/*
** err_???_print() functions are named systematically, and are all static.
**
** err_[ev][crx][fn]_print():
** -- e takes ellipsis argument
** -- v takes va_list argument
** -- c conditionally exits
** -- r returns (no exit)
** -- x exits (no return)
** -- f takes file pointer
** -- n no file pointer (use errout)
**
** NB: no-return and printf-like can only be attached to declarations, not definitions.
*/
static void err_vxf_print(FILE *fp, int flags, int estat, const char *format, va_list args)
NORETURN();
static void err_vxn_print(int flags, int estat, const char *format, va_list args)
NORETURN();
static void err_exn_print(int flags, int estat, const char *format, ...)
NORETURN() PRINTFLIKE(3,4);
static void err_terminate(int flags, int estat) NORETURN();
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
const char jlss_id_stderrmin_c[] = "#(#)$Id: stderrmin.c,v 9.6 2009/03/02 20:27:38 jleffler Exp $";
#endif /* lint */
/*
** Set default log options, returning old value.
** Setting ERR_EXIT and ERR_ABORT is permitted but not recommended.
*/
int err_setlogopts(int new_opts)
{
int old_opts = err_flags;
err_flags = new_opts & ERR_LOGOPTS;
return(old_opts);
}
/* Return default log options */
int err_getlogopts(void)
{
return(err_flags);
}
/* Change the definition of 'stderr', reporting on the old one too */
/* NB: using err_stderr((FILE *)0) simply reports the current 'stderr' */
FILE *(err_stderr)(FILE *newerr)
{
FILE *old;
if (errout == 0)
errout = stderr;
old = errout;
if (newerr != 0)
errout = newerr;
return(old);
}
/* Return stored basename of command */
const char *(err_getarg0)(void)
{
return(arg0);
}
/* Store basename of command, excluding trailing slashes */
void (err_setarg0)(const char *argv0)
{
/* Ignore three pathological program names -- NULL, "/" and "" */
if (argv0 != 0 && *argv0 != '\0' && (*argv0 != '/' || *(argv0 + 1) != '\0'))
{
const char *cp;
size_t nbytes = sizeof(arg0) - 1;
if ((cp = strrchr(argv0, '/')) == 0)
{
/* Basename of file only */
cp = argv0;
}
else if (*(cp + 1) != '\0')
{
/* Regular pathname containing slashes but not trailing slashes */
cp++;
}
else
{
/* Skip backwards over trailing slashes */
const char *ep = cp;
while (ep > argv0 && *ep == '/')
ep--;
/* Skip backwards over non-slashes */
cp = ep;
while (cp > argv0 && *cp != '/')
cp--;
assert(ep >= cp);
cp++;
nbytes = (size_t)(ep - cp) + 1;
if (nbytes > sizeof(arg0) - 1)
nbytes = sizeof(arg0) - 1;
}
strncpy(arg0, cp, nbytes);
arg0[nbytes] = '\0';
}
}
const char *(err_rcs_string)(const char *s2, char *buffer, size_t buflen)
{
const char *src = s2;
char *dst = buffer;
char *end = buffer + buflen - 1;
/*
** Bother RCS! We've probably been given something like:
** "$Revision: 9.6 $ ($Date: 2009/03/02 20:27:38 $)"
** We only want to emit "7.5 (2001/08/11 06:25:48)".
** Skip the components between '$' and ': ', copy up to ' $',
** repeating as necessary. And we have to test for overflow!
** Also work with the unexpanded forms of keywords ($Keyword$).
** Never needed this with SCCS!
*/
while (*src != '\0' && dst < end)
{
while (*src != '\0' && *src != '$')
{
*dst++ = *src++;
if (dst >= end)
break;
}
if (*src == '$')
src++;
while (*src != '\0' && *src != ':' && *src != '$')
src++;
if (*src == '\0')
break;
if (*src == '$')
{
/* Unexpanded keyword '$Keyword$' notation */
src++;
continue;
}
if (*src == ':')
src++;
if (*src == ' ')
src++;
while (*src != '\0' && *src != '$')
{
/* Map / in 2009/02/15 to dash */
/* Heuristic - maps slashes surrounded by digits to dashes */
char c = *src++;
if (c == '/' && isdigit(*src) && isdigit(*(src-2)))
c = '-';
*dst++ = c;
if (dst >= end)
break;
}
if (*src == '$')
{
if (*(dst-1) == ' ')
dst--;
src++;
}
}
*dst = '\0';
return(buffer);
}
/* Format a time string for now (using ISO8601 format) */
/* Allow for future settable time format with tm_format */
static char *err_time(char *buffer, size_t buflen)
{
time_t now;
struct tm *tp;
now = time((time_t *)0);
tp = localtime(&now);
strftime(buffer, buflen, tm_format, tp);
return(buffer);
}
/* Most fundamental (and flexible) error message printing routine - always returns */
static
At least for Ubuntu (12.04 and later, to my certain knowledge), there's an errno utility you can easily install via apt-get install moreutils. (Thanks to #kevinoid and #leo for the update.)
$ errno 98
EADDRINUSE 98 Address already in use
$ errno EINVAL
EINVAL 22 Invalid argument
This works on Ubuntu 9.04:
user#host:~$ grep EINVAL /usr/include/asm-generic/errno*.h
/usr/include/asm-generic/errno-base.h:#define EINVAL 22 /* Invalid argument */
You can also try a Python script:
import errno
from os import strerror
from sys import argv
print strerror(errno.__dict__[argv[1]]
The function
strerror()
Is possibly what you're looking for, but I don't know of a command that exposes that to any shell offhand.
MKS exposes the command line strerror
Tried
grep EINVAL /usr/include/sys/errno.h
and seen what comes back?
#! /bin/bash -f
errorDir="/usr/include/asm-generic"
strError="$1"
numericVal=awk -v pat="$strError" '$0 ~ pat{print $3}' $errorDir/errno-base.h $errorDir/errno.h
perror $numericVal
Caution: As this script uses the location of ERROR MACROS,this might not be portable although it works on my system.
Rob Wells is partially correct. Unfortunately /usr/include/asm/errno.h is nonstandard. You really need to grep /usr/include/errno.h and /usr/include/*/errno.h.
To make this errorcommand, try adding this to your .bashrc file:
function errorcommand
{
grep "${1}" /usr/include/errno.h /usr/include/*/errno.h
}
Which works like this:
Rob Wells is partially correct. Unfortunately /usr/include/asm/errno.h is nonstandard. You really need to grep /usr/include/errno.h and /usr/include/*/errno.h.
To make this errorcommand, try adding this to your .bashrc file:
function errorcommand
{
grep "${1}" /usr/include/errno.h /usr/include/*/errno.h
}
Which works like this:
$ errorcommand EINV
/usr/include/sys/errno.h:#define EINVAL 22 /* Invalid argument */
$
A compact bash script that exactly does what you want:
#!/bin/bash -f
file="/tmp/prog$$.c"
out="/tmp/prog$$"
if [ $# -ne 1 ]
then
echo "Usage: $0 ERROR-NO"
exit 1
fi
echo "#include <stdio.h>" >> $file
echo "#include <errno.h>" >> $file
echo "int main(){" >> $file
echo "printf(\"$1:%s\n\",strerror($1));" >> $file
echo "}" >> $file
gcc $file -o $out &> /dev/null
if [ $? == "0" ]
then
$out
rm -f $out
else
echo "Syntax Error: $1 Unknown"
fi
# cleanup the file
rm -f $file
On my corporate box /usr/include wasn't available. So I put this portable simple solution (if you have Python) into my init files. You can torture it into a one-liner if you wish:
function strerror () {
python -c "import os, errno; print(os.strerror(errno.$1))"
}
There's no standard utility to do this. I believe your best bet is to write such a utility yourself. Use strerror() to print the associated error message.
For people that want a quick, on-liner:
find /usr/include/ -name errno*.h -exec grep ERRNO {} +
e.g.
[x#localhost]$ find /usr/include/ -name errno*.h -exec grep EINVAL {} +
/usr/include/asm-generic/errno-base.h:#define EINVAL 22 /* Invalid argument */
[x#localhost]$ find /usr/include/ -name errno*.h -exec grep 111 {} +
/usr/include/asm-generic/errno.h:#define ECONNREFUSED 111 /* Connection refused */
Here is a short C++ program that handles both numeric and symbolic errors. Given the option -l as its very first argument, it lists all known error symbols and then exits. Otherwise iterates over all arguments and prints the error text, and nothing else, for each argument.
There is nothing much here that has not been mentioned earlier, but it does it all in a single source file, not counting table.h, which is generated.
To build:
./table.sh > table.h
g++ -O2 -Wall -W -Wextra -o errno errno.cc
The program is in C, except for the C++ iteration in list_and_exit().
errno.cc
# include <string.h>
# include <stdio.h>
# include <stdlib.h>
# include <errno.h>
# include <ctype.h>
struct ErrSym {
char const *name;
unsigned char value; // 0..255
};
static ErrSym const es[] = {
# include "table.h"
};
static int cmp(char const *a, ErrSym const *b) {
return strcmp(a, b->name);
}
static ErrSym const *find_by_name(char *needle) {
typedef int (*IVV)(void const *, void const *);
static int const n = (sizeof es / sizeof *es);
return (ErrSym*)bsearch(needle, es, n,
sizeof *es, (IVV)cmp);
}
static void list_and_exit() {
for (auto &e : es)
printf("%3d %-15s %s\n",
e.value, e.name, strerror(e.value));
exit(0);
}
static void handle_arg(char *arg) {
if (isdigit(arg[0]))
printf("%s\n", strerror(atoi(arg)));
else if (ErrSym const *p = find_by_name(arg))
printf("%s\n", strerror(p->value));
else
printf("Unknown error symbol: %s\n", arg);
}
int main(int argc, char *argv[]) {
if (argc > 1 && 0 == strcmp("-l", argv[1]))
list_and_exit();
for (int i = 1; i < argc; i++)
handle_arg(argv[i]);
return 0;
}
With the assumption that error numbers are less than 256, ErrSym.value is defined as unsigned char, so that the compiler can warn about values that are out of range.
To generate table.h, the trick (as mentioned in a comment above) is to use the C compiler and the preprocessor.
table.sh
#!/bin/bash
trap 'rm -f tmp.c' EXIT
echo '#include <errno.h>' > tmp.c
#
# -E Run the preprocessor only
# -dM At end, dump preprocessor symbols
# According to documentation, but not tested, these
# options should work also with clang and Intel's icc.
gcc -E -dM tmp.c | ./table.pl | sort
table.pl
#!/usr/bin/perl -n
#
# Convert '#define EACCES 13' to '{ "EACCES", 13 },'
# Skip lines that do not match
#
# By happy concidence, all names beginning
# with E are error numbers
#
next unless (/^#define +(E\S+) +(\S+)/);
$_ = sprintf("{%-18s %10s},\n", qq{"$1",}, $2);
s/, /, /; # Remove excess whitespace
print;
The output from errno -l is sorted by error symbol. Say errno -l | sort to sort by error number.

Resources