From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,60e2922351e0e780 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2003-11-21 02:55:52 PST Path: archiver1.google.com!news2.google.com!fu-berlin.de!news-FFM2.ecrc.net!news.iks-jena.de!not-for-mail From: Lutz Donnerhacke Newsgroups: comp.lang.ada Subject: Generic thinbinding toolkit for C Date: Fri, 21 Nov 2003 10:55:51 +0000 (UTC) Organization: IKS GmbH Jena Message-ID: References: <3FB0B57D.6070906@noplace.com> <3FB22125.1040807@noplace.com> <3FB3751D.5090809@noplace.com> <3FB8B9BC.5040505@noplace.com> <3FBA1118.4060105@noplace.com> <0fxub.48425$bQ3.12107@nwrdny03.gnilink.net> <3FBC2EEC.212A1B5@cogeco.ca> NNTP-Posting-Host: taranis.iks-jena.de X-Trace: branwen.iks-jena.de 1069412151 29514 217.17.192.37 (21 Nov 2003 10:55:51 GMT) X-Complaints-To: usenet@iks-jena.de NNTP-Posting-Date: Fri, 21 Nov 2003 10:55:51 +0000 (UTC) User-Agent: slrn/0.9.7.4 (Linux) Xref: archiver1.google.com comp.lang.ada:2791 Date: 2003-11-21T10:55:51+00:00 List-Id: * Warren W. Gay VE3WWG wrote: > Lutz Donnerhacke wrote: >> * Warren Gay wrote: >>>What thinbind would be required to do, is to preprocess the header >>>file somewhat differently than the C's preprocessor. Instead of >> >> This destroys most of the original C API in a unusable way. > > Rubbish. I beg to differ. You have to write down an example C source using the API for the requested thinbinding. Then you preprocess this source code and now you can parse the result in order to find out what really happend. Example: Thinbinding to getc(3). #include return getc(stdin); results in extern struct _IO_FILE *stdin; return _IO_getc (stdin); where struct _IO_FILE { int _flags; char* _IO_read_ptr; char* _IO_read_end; char* _IO_read_base; char* _IO_write_base; char* _IO_write_ptr; char* _IO_write_end; char* _IO_buf_base; char* _IO_buf_end; char *_IO_save_base; char *_IO_backup_base; char *_IO_save_end; struct _IO_marker *_markers; struct _IO_FILE *_chain; int _fileno; int _flags2; __off_t _old_offset; unsigned short _cur_column; signed char _vtable_offset; char _shortbuf[1]; _IO_lock_t *_lock; __off64_t _offset; void *__pad1; void *__pad2; int _mode; char _unused2[15 * sizeof (int) - 2 * sizeof (void *)]; }; struct _IO_marker { struct _IO_marker *_next; struct _IO_FILE *_sbuf; int _pos; }; typedef long int __off_t; typedef long long int __off64_t; typedef void _IO_lock_t; You will notice, that the original API vanished by preprocessing. It introduces a huge structure and a different name. What do you expect as the generated Ada-API? > The whole purpose of preprocessing it in thinbind is to compile > a package for Ada use. It need _NOT_ be the same. You only > need to arrive at the correct internal answers. There are > many ways to skin a cat (pardon the expression to cat lovers > out there). You wrote about preprocessing and then searching the API. This does not work. You have to specify the API and preprocessing it to find the real C code. > As long as the end results work, then you as the user, do not care about > 1 pass, 3 passes or n passes. You might care about performance, but given > the choice between coding a thin binding by hand or having your computer > do it for you, I think the choice is still and easy one. The user will use "getc(FILE *)". He will never touch the bloody interenal. He will even not user _IO_getc(struct _IO_FILE *) despite it's very close. You might complain about high level library calls. Ok, let's go downstairs. #include #include #include int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); FD_CLR(int fd, fd_set *set); FD_ISSET(int fd, fd_set *set); FD_SET(int fd, fd_set *set); FD_ZERO(fd_set *set); will result in int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); (((fd_set *set)->__fds_bits)[((int fd) / (8 * sizeof (__fd_mask)))] &= ~((__fd_mask) 1 << ((int fd) % (8 * sizeof (__fd_mask))))); (((fd_set *set)->__fds_bits)[((int fd) / (8 * sizeof (__fd_mask)))] & ((__fd_mask) 1 << ((int fd) % (8 * sizeof (__fd_mask))))); (((fd_set *set)->__fds_bits)[((int fd) / (8 * sizeof (__fd_mask)))] |= ((__fd_mask) 1 << ((int fd) % (8 * sizeof (__fd_mask))))); do { unsigned int __i; fd_set *__arr = (fd_set *set); for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) ((__arr)->__fds_bits)[__i] = 0; } while (0); You will never find anything about the FD_* API in a preprocessed header. > The challenge is to do it well, to make it work in a platform > neutral sort of way (the generated thin binding should look > consistent in all platforms, so that the clients of the binding > won't fail to compile). The challenge is to convert this to: type fd_set is array(1 .. x) of Boolean; for fd_set'Size use x; for fd_set'Component_Size use 1; pragma Pack(fd_set); and implement FD_* over this type. >> Hard work. Especially when considering marco expansion down to the plain >> syscall (Linux). > > You don't care about operating system details. You only care about > things at the C compiler level. Expansion to the syscall level happens in C-Header files. #include pause(); will be translated to: pause(); where static inline int pause(void) { long __res; __asm__ volatile ("int $0x80" : "=a" (__res) : "0" (29)); do { if ((unsigned long)(__res) >= (unsigned long)(-125)) { errno = -(__res); __res = -1; } return (int) (__res); } while (0); } Yes, that's exactly the thin binding of my kernel_calls.ads (in linux_ix86.adb) > Yes it is difficult, but this is no more difficult than what GCC does now > for optimization and compilation. I still beg to differ. > I am not suggesting that the macro expansions be ignored. But > some of them have to be expanded along the way to provide the > correct view of the code. But the other objective is to come > away with macro definitions that fold into constants. These > can be coded into an Ada spec. A tricky process to be sure, > but this can be done. >From doing this by hand, I would gladly enjoy any hit for automatisms. >> So you have to start from the man page and fill in the blanks by designing >> the Ada types(!) and calls like expected. > > Your point isn't clear to me. Name an example. man 2 select. > Lets take an example: > > #define increment(x) (++x) Let's assume the manpage contains a description of 'increment' describing it for 'int' types. So you gain "function increment(x : int) returns int;" from the man page (API). Now you can use the preprocessor to find out, what the thin binding has to do. This gets more complicated if there is a macro and a library call (for address reference or linking): extern int increment(int); #define increment(x) ((x)+1) > Now you're right that there is no type information here. Determine the Ada-Type of "struct fd_set". > Ada. If a C compiler can translate C code into object > code, then I am not convinced that another C compiler > could not generate Ada code. This would be no Ada code. It would be C Code with Ada syntax. Ugly and unusable. In order to transform header files, you have to parse the API description and define types, functions and procedures from there. Then you have to map this to C. This binding can be very thin, but strongly typed. BTDT. > In this case, we are only interested in a thin binding, not a complete > translation of the code. You proposes to recode the existing thin binding to the library from one language to another. This does not work. Every binding models the imported API in the importing language. This has to be done seperatly. A thin binding written in C to the glibc or a kernel has to rewritten from scratch in Ada. > I have already acknowledged the practical need for a hints file. This hints file has to contain the API, because it can't regained from the C header code (too much type information is missing). > I do agree that there will be some C things that it will be hard to > automate completely. extern int printf(char * format, ...); > Perhaps some Computer Science major will take this > project on? Professors out there looking for project > ideas? Let's see if this is practical! Good luck.