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 21:12:43 PST Path: archiver1.google.com!news2.google.com!fu-berlin.de!news-fra1.dfn.de!npeer.de.kpn-eurorings.net!news.tele.dk!news.tele.dk!small.news.tele.dk!feed.cgocable.net!read2.cgocable.net.POSTED!53ab2750!not-for-mail Message-ID: <3FBEF03D.6E3474BE@nospam.cogeco.ca> From: Warren Gay X-Mailer: Mozilla 4.77 [en] (Windows NT 5.0; U) X-Accept-Language: en MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Re: Generic thinbinding toolkit for C 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> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Date: Sat, 22 Nov 2003 00:12:29 -0500 NNTP-Posting-Host: 24.150.168.167 X-Complaints-To: abuse@cogeco.ca X-Trace: read2.cgocable.net 1069477967 24.150.168.167 (Sat, 22 Nov 2003 00:12:47 EST) NNTP-Posting-Date: Sat, 22 Nov 2003 00:12:47 EST Organization: Cogeco Cable Xref: archiver1.google.com comp.lang.ada:2839 Date: 2003-11-22T00:12:29-05:00 List-Id: Lutz Donnerhacke wrote: > * 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 > ... > > 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. See my earlier corrected post. I think a generated C wrapper is best for macro-ized code, for the reasons you cite, and I conceded that point. > 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. OK. But this issue isn't unsolvable! We just have to take a different approach to handle these cases. You isolate an instance of the macro, and paramaterize it into a C wrapper routine. Then thin bind generates a pragma Import(C,Wrapped_FD_SET,"_Wrapped_FD_SET") and an appropriate procedure definition. Compile and link with the thin binding, C compile the wrapper module, and link. A little bit more overhead, but it's solved. > > 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. I don't think you would implement the fd_set with anything other than an opaque type in the thin binding. Like you pointed out, there isn't enough information for more than that. So the best you can do is implement something opaque, and the same size that can be used with the wrapper routines. I didn't expect to improve upon the C code you know ;-) > >> 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) OK, but _once again_, this can be solved with the wrapper module approach. You shout defeat, instead of looking for answers. ;-) > I still beg to differ. And now? > > 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. Ok, so we're on the same page there at least ;-) > >> 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. Like I pointed out earlier, you're not going to implement specifics for types that are presented to client programs as opaque. I don't expect to do any more than that for the Ada spec either (at least if I understand your point here). > > 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) Ok, but who says I have to define this as: pragma import(C,Increment,"increment") ?? I can generate anything I want, including linking names that are very unlikly to collide. A hints (or config) file could even pick an override name if necessary. You see problems, but I see solutions. > > Now you're right that there is no type information here. > > Determine the Ada-Type of "struct fd_set". Once again: Opaque. I already have all the operations I need for the type (clear, test, set etc.) I don't need to see the internals in the Ada code. Neither does your C code, for that matter. > > 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. Yes, you are right . But a generated wrapper routine would take care of the ugly C internals, only generating interfaces into and out of it (see above). > 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. There is no doubt in my mind that the process needs either a hints file or a config file to specify what you are interested in. There are a number of difficult problems, but all or most of them are solvable with a little bit of help from the programmer. Tools reduce work -- not necessarily completely eliminate it. Remember, that my goal would be to specify a minimum amount of API, and have the thinbind take care of the details that pertain to that platform. This is the same idea as recompiling a C program that #includes that same file. The only difference is that you want to translate/interface some of that include file code into Ada terms so that you can use it. Besides functions and macro functions, the most important things are the macro constants, structures and types. Note also that because you're starting with C code, I don't expect the resulting thin binding to be strongly typed. It might be stronger with the help of hints/config entries, but I would not have the unrealistic expectation that the spec is going to be strongly typed. That is the job for the thick binding, which is now easier for you to write! > > 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 think you must have misunderstood my intentions. This is partly because I stated a few things wrong earlier, and inserted feet in mouth. I can call getuid() from Ada, almost as easily as I can from C. The _problem_ is that I don't have a spec for that function (with the matching sized type), for every platform. With a generated thin binding that includes the necessary spec, calling getuid() from Ada becomes effortless and is in all other respects, including efficiency, on par with C. So if I can determine the size and types of the return value for getuid(), then there is no reason thinbind cannot generate a spec, a type (if necessary), and a pragma import statement. In this case, no C wrapper code is required and everyone is still happy. > > 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). This of course, depends on how far down the road to compiling you want to go. The C compiler knows about types. There is no theoretical reason that thinbind could not also (only the amount of complexity and work, but no worse than GCC). You are right in that it is _easier_ to configure certain things like type information. However, I would still expect thinbind to be able to determine the size of the types in question etc. and reliably generate thin bindings to match, given enough starting information. Later renditions of the tool could do better, as it becomes more C aware. > > I do agree that there will be some C things that it will be hard to > > automate completely. > > extern int printf(char * format, ...); This one is easy! Don't allow it! You shouldn't be using this from Ada anyway ;-) If you need to do this, then use C for that. You constantly look for defeat. Look for solutions: that's what programmers normally do. Otherwise, we might as well shut everything down and say "it's too hard", and watch golf instead. I don't know about you, but watching golf puts me to sleep ;-) > > 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. Somebody took on the GNAT compiler! Thanks to optimists like them, they saw it as an oportunity to solve a problem. Now many of us benefit from their fine efforts (and continuing thanks to ACT). Maybe someday, we'll benefit from a thin binding generator. Maybe even ACT is spoiling for more fun? ;-) Be positive. It helps. -- Warren W. Gay VE3WWG http://home.cogeco.ca/~ve3wwg [Remove the nospam from the email address: blame the worms]