Обсуждение: Autoconf'd test for int64
Attached is a patch that uses autoconf to determine whether there is a working 64-bit-int type available. In playing around with it on my machine, I found that gcc provides perfectly fine support for "long long" arithmetic ... but sprintf() and sscanf(), which are system-supplied, don't work :-(. So the autoconf test program does a cursory test on them too. If we find that a lot of systems are like this, it might be worth the trouble to implement binary<->ASCII conversion of int64 ourselves rather than relying on sprintf/sscanf to handle the data type. regards, tom lane *** src/configure.in.orig Sat Aug 15 11:52:03 1998 --- src/configure.in Sun Aug 16 16:41:24 1998 *************** *** 522,528 **** #endif main() { double d = DBL_MIN; if (d != DBL_MIN) exit(-1); else exit(0); }], AC_MSG_RESULT(yes), ! [AC_MSG_RESULT(no) AC_DEFINE(HAVE_DBL_MIN_PROBLEM)]) dnl Checks for library functions. AC_PROG_GCC_TRADITIONAL --- 522,604 ---- #endif main() { double d = DBL_MIN; if (d != DBL_MIN) exit(-1); else exit(0); }], AC_MSG_RESULT(yes), ! [AC_MSG_RESULT(no) AC_DEFINE(HAVE_DBL_MIN_PROBLEM)], ! AC_MSG_RESULT(assuming ok on target machine)) ! ! dnl Check to see if we have a working 64-bit integer type. ! AC_MSG_CHECKING(whether 'long int' is 64 bits) ! AC_TRY_RUN([#include <stdio.h> ! typedef long int int64; ! #define INT64_FORMAT "%ld" ! ! int64 a = 20000001; ! int64 b = 40000005; ! ! int does_int64_work() ! { ! int64 c,d,e; ! char buf[100]; ! ! if (sizeof(int64) != 8) ! return 0; /* doesn't look like the right size */ ! ! /* we do perfunctory checks on multiply, divide, sprintf, sscanf */ ! c = a * b; ! sprintf(buf, INT64_FORMAT, c); ! if (strcmp(buf, "800000140000005") != 0) ! return 0; /* either multiply or sprintf is busted */ ! if (sscanf(buf, INT64_FORMAT, &d) != 1) ! return 0; ! if (d != c) ! return 0; ! e = d / b; ! if (e != a) ! return 0; ! return 1; ! } ! main() { ! exit(! does_int64_work()); ! }], ! [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_LONG_INT_64)], ! AC_MSG_RESULT(no), ! AC_MSG_RESULT(assuming not on target machine)) ! ! AC_MSG_CHECKING(whether 'long long int' is 64 bits) ! AC_TRY_RUN([#include <stdio.h> ! typedef long long int int64; ! #define INT64_FORMAT "%Ld" ! ! int64 a = 20000001; ! int64 b = 40000005; ! ! int does_int64_work() ! { ! int64 c,d,e; ! char buf[100]; ! ! if (sizeof(int64) != 8) ! return 0; /* doesn't look like the right size */ ! ! /* we do perfunctory checks on multiply, divide, sprintf, sscanf */ ! c = a * b; ! sprintf(buf, INT64_FORMAT, c); ! if (strcmp(buf, "800000140000005") != 0) ! return 0; /* either multiply or sprintf is busted */ ! if (sscanf(buf, INT64_FORMAT, &d) != 1) ! return 0; ! if (d != c) ! return 0; ! e = d / b; ! if (e != a) ! return 0; ! return 1; ! } ! main() { ! exit(! does_int64_work()); ! }], ! [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_LONG_LONG_INT_64)], ! AC_MSG_RESULT(no), ! AC_MSG_RESULT(assuming not on target machine)) dnl Checks for library functions. AC_PROG_GCC_TRADITIONAL *** src/include/config.h.in.orig Sat Aug 15 11:54:54 1998 --- src/include/config.h.in Sun Aug 16 16:33:22 1998 *************** *** 219,224 **** --- 219,230 ---- /* Set to 1 if your DBL_MIN is problematic */ #undef HAVE_DBL_MIN_PROBLEM + /* Set to 1 if type "long int" works and is 64 bits */ + #undef HAVE_LONG_INT_64 + + /* Set to 1 if type "long long int" works and is 64 bits */ + #undef HAVE_LONG_LONG_INT_64 + /* * Code below this point should not require changes */ *** src/include/utils/int8.h.orig Wed Jul 8 10:10:30 1998 --- src/include/utils/int8.h Sun Aug 16 16:37:51 1998 *************** *** 23,51 **** #ifndef INT8_H #define INT8_H ! #if defined(__alpha) || defined(PPC) typedef long int int64; - #define INT64_FORMAT "%ld" ! ! #elif defined(__GNUC__) && defined(i386) typedef long long int int64; - #define INT64_FORMAT "%Ld" - #else typedef long int int64; - #define INT64_FORMAT "%ld" #endif - - - /* - #if sizeof(int64) == 8 - #define HAVE_64BIT_INTS 1 #endif - */ - extern int64 *int8in(char *str); extern char *int8out(int64 * val); --- 23,44 ---- #ifndef INT8_H #define INT8_H ! #ifdef HAVE_LONG_INT_64 ! /* Plain "long int" fits, use it */ typedef long int int64; #define INT64_FORMAT "%ld" ! #else ! #ifdef HAVE_LONG_LONG_INT_64 ! /* We have working support for "long long int", use that */ typedef long long int int64; #define INT64_FORMAT "%Ld" #else + /* Won't actually work, but fall back to long int so that int8.c compiles */ typedef long int int64; #define INT64_FORMAT "%ld" + #define INT64_IS_BUSTED #endif #endif extern int64 *int8in(char *str); extern char *int8out(int64 * val);
> Attached is a patch that uses autoconf to determine whether there is > a working 64-bit-int type available. Using autoconf for things sounds great. I've been relying on scrappy for that stuff, and find it a mystery myself. Marc or someone, would you be willing to write a few sentences on how to make incremental changes to the Postgres autoconfig system? I'll put it into the Developer's Guide, and could make a stab at using it elsewhere. > In playing around with it on my machine, I found that gcc provides > perfectly fine support for "long long" arithmetic ... but sprintf() > and sscanf(), which are system-supplied, don't work :-(. So the > autoconf test program does a cursory test on them too. Sorry to hear the formatting routines are broken. sprintf() and sscanf() are HP supplied? Doesn't gcc have its own library also?? > If we find that a lot of systems are like this, it might be worth > the trouble to implement binary<->ASCII conversion of int64 ourselves > rather than relying on sprintf/sscanf to handle the data type. Yuck. Whaddya mean "we"; *my* system works fine :) - Tom
On Sun, 16 Aug 1998, Thomas G. Lockhart wrote: > > Attached is a patch that uses autoconf to determine whether there is > > a working 64-bit-int type available. > > Using autoconf for things sounds great. I've been relying on scrappy for > that stuff, and find it a mystery myself. Marc or someone, would you be > willing to write a few sentences on how to make incremental changes to > the Postgres autoconfig system? I'll put it into the Developer's Guide, > and could make a stab at using it elsewhere. Sorry to say, but from my perspective as well its "funky magic"...I cheat alot by looking at autoconf from other packages to try and recreate what I want to do, as well as spend alot of time in the info pages... I don't think this is something that can be easily explained in "a few sentences" :( Marc G. Fournier Systems Administrator @ hub.org primary: scrappy@hub.org secondary: scrappy@{freebsd|postgresql}.org
> Sorry to say, but from my perspective as well its "funky > magic"... > I don't think this is something that can be easily explained in "a > few sentences" :( Well, no harm in asking :) - Tom^H^H^HThomas
"Thomas G. Lockhart" <lockhart@alumni.caltech.edu> writes: > Using autoconf for things sounds great. I've been relying on scrappy for > that stuff, and find it a mystery myself. Marc or someone, would you be > willing to write a few sentences on how to make incremental changes to > the Postgres autoconfig system? Well, there's really no substitute for reading the autoconf manual ;-) But basically the idea is that you don't want to have your code #ifdef'ing on system ID symbols except in very specific circumstances. Usually what you really want to know is "does feature X exist here?", and the right way to handle that is to have a direct test for feature X. If you take that approach your code is a lot more likely to work out-of-the-box on a new system. Not to mention the fact that some systems like HPUX and Linux come in a lot of flavors --- testing the system ID symbols isn't good enough there anyway. What autoconf does is provide a system whereby you can make exactly the tests you need during configuration, and have the results available when your code is being compiled. The results are usually expressed in the form of configuration symbols that get defined (or not) in config.h. You can also have autoconf apply system-specific edits to other places like makefiles, but config.h is most often the file to tweak. To take the particular example at hand, I had to go through the following steps: 1. Ask myself what we really wanted to know. What we wanted to know, it seemed like, was whether either "long int" or "long long int" could be used as a 64-bit integer type. So I invented some configuration symbol names that would carry this info from autoconf to the compile-time tests needed in int8.h: /* Set to 1 if type "long int" works and is 64 bits */ #undef HAVE_LONG_INT_64 /* Set to 1 if type "long long int" works and is 64 bits */ #undef HAVE_LONG_LONG_INT_64 2. I put the above lines into src/include/config.h.in, which is the master file that autoconf will edit during configuration to create the localized version src/include/config.h (.in is the usual convention for indicating an autoconf master file). Autoconf provides automatic support for changing "#undef X" into "#define X something" when appropriate, so we start with the "#undef" format. 3. Then I needed to figure out how to test these conditions. Basically what autoconf can do is to (try to) compile and run little test programs; if it succeeds then it figures that particular feature is there. So I wrote a little program that checks sizeof(long long int) (to make sure it's 8) and also tries to do some simple arithmetic to make sure the answers come out right. You can see the details in the patch, but the important point is that if long long isn't OK, the program will either fail to compile at all, or will exit with a nonzero return status (which is program failure by Unix convention). Autoconf will only believe the test succeeded if the program compiles and exits with zero status when run. 4. After I'd tested the test program to my satisfaction, I wrapped it into this autoconf code: AC_MSG_CHECKING(whether 'long long int' is 64 bits) AC_TRY_RUN([ ... test program code here ... ], [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_LONG_LONG_INT_64)], AC_MSG_RESULT(no), AC_MSG_RESULT(assuming not on target machine)) AC_TRY_RUN is a macro that's basically like an if-then-else structure. If the test program (whose text is the first argument) succeeds, the second argument is executed; if the test fails, the third argument is executed; and if autoconf knows it is cross-compiling for another machine and therefore can't run a test program at all, it doesn't try but just executes the fourth argument. Usually that last alternative should be the most conservative assumption. The AC_MSG macros are just user interface aids (they generate all that junk that the configure script prints as it runs). The important aspect is the AC_DEFINE() macro --- if that gets executed, it cues Autoconf to convert "#undef HAVE_LONG_LONG_INT_64" to "#define HAVE_LONG_LONG_INT_64 1" later on when it's generating config.h from config.h.in. (I could give AC_DEFINE a second argument if I wanted to define the symbol as some particular string instead of "1".) In the other cases, AC_DEFINE is not executed so that line of config.h.in will be left unmodified. The other thing to know to read this is that square brackets are m4's quoting convention. I made another copy that was exactly the same but it works on "long int" and defines HAVE_LONG_INT_64 if it wins. 5. Then I ran autoconf to generate a configure shell script from the configure.in source code, and I was done. 6. AC_TRY_RUN is the sledgehammer of Autoconf programming --- you only need it if you need to verify some unusual detail of a system's run-time behavior. Most of the standard sorts of problems can be dealt with using simpler Autoconf macros. For example, if I had been satisfied just to test whether the declaration "long long int" would compile, I could've just done AC_TRY_COMPILE(, [ long long int x; ], [success action], [fail action]) which would compile the code but not try to run it. There are even simpler macros that handle most of the really common cases. For example, PostgreSQL's configure.in includes AC_CHECK_HEADERS(limits.h) which tries to compile a program that says "#include <limits.h>", and if it succeeds then it automatically defines HAVE_LIMITS_H. (We still have to remember to put #undef HAVE_LIMITS_H into config.h.in, however, or the AC_DEFINE would have no visible effect.) BTW this last example should cue you that there are conventions for choosing configuration symbol names in Autoconf --- a symbol that indicates that <stdlib.h> exists should be called HAVE_STDLIB_H, and not anything else; if you violate these conventions you risk confusing autoconf experts, or even breaking some other part of configuration. (A while back we had a configuration bug because HAVE_HISTORY was getting used for two different purposes: both to indicate whether <history.h> exists and whether libhistory exists to be linked with. Following the convention prevents this error, since HAVE_HISTORY_H refers to the include file and HAVE_LIBHISTORY to the library.) 7. The configure script generated by Autoconf is a self-contained shell script that will run on darn near any Unix platform. But to generate configure from configure.in, you need to have Autoconf itself installed, and you also need GNU m4 because Autoconf is really just a script in the m4 macro processing language. You can find these at any GNU archive site if you don't have 'em already. Both are painless to install. 8. There's really no substitute for reading the autoconf manual ;-). But maybe this will motivate you to go do that. regards, tom lane
"Thomas G. Lockhart" <lockhart@alumni.caltech.edu> writes: >> In playing around with it on my machine, I found that gcc provides >> perfectly fine support for "long long" arithmetic ... but sprintf() >> and sscanf(), which are system-supplied, don't work :-(. So the >> autoconf test program does a cursory test on them too. > Sorry to hear the formatting routines are broken. sprintf() and sscanf() > are HP supplied? Doesn't gcc have its own library also?? gcc supplies low-level routines that implement doubleword arithmetic, but it doesn't attempt to supplant the local libc. >> If we find that a lot of systems are like this, it might be worth >> the trouble to implement binary<->ASCII conversion of int64 ourselves >> rather than relying on sprintf/sscanf to handle the data type. > Yuck. Whaddya mean "we"; *my* system works fine :) I'm not eager to do it either --- I hope to have upgraded to HPUX 10 before I actually need to do anything with int8. I was just throwing that idea out in case someone else needed int8 bad enough to want to make it happen. regards, tom lane
> I'm not eager to do it either --- I hope to have upgraded to HPUX 10 > before I actually need to do anything with int8. I was just throwing > that idea out in case someone else needed int8 bad enough to want to > make it happen. The fact that machines need to provide their own i/o means that those relying on gcc for compiling but non-gnu i/o libraries aren't likely to succeed on 32-bit machines without rolling your own :( - Tom
> 8. There's really no substitute for reading the autoconf manual ;-). > But maybe this will motivate you to go do that. Sure, didn't even know one existed. Don't know if it is shipped on my machine, and don't know where to look for one. Oh boy, maybe I'll get to use GNU info! Not. Is there a hardcopy or html version somewhere? *sigh* - Tom
"Thomas G. Lockhart" <lockhart@alumni.caltech.edu> writes: >> 8. There's really no substitute for reading the autoconf manual ;-). > Sure, didn't even know one existed. Don't know if it is shipped on my > machine, and don't know where to look for one. > Oh boy, maybe I'll get to use GNU info! Not. Is there a hardcopy or html > version somewhere? *sigh* Picky picky. The manual comes with the autoconf distribution tarball. The master copy is in GNU "texinfo" format, looks like. I always use the GNU-info-format version of it, which gets installed automatically by autoconf's install script. But this is convenient for me because I use the One True Editor, Emacs ;-) ;-). If you don't live in Emacs then I agree info format is less than convenient. It is possible to generate html or latex (hence PostScript, hence nice- looking hardcopy) from texinfo sources. (Basically texinfo is the same idea as SGML but a few years before its time.) I'm not an expert on how to do either process, not having ever felt the need. If you look around the net you can certainly get the tools for this, and possibly even find the autoconf manual already converted to a format you like. Or you can just read the texinfo source file. It's certainly no less legible than sgml source. regards, tom lane
On Sun, 16 Aug 1998, Tom Lane wrote: > "Thomas G. Lockhart" <lockhart@alumni.caltech.edu> writes: > >> 8. There's really no substitute for reading the autoconf manual ;-). > > > Sure, didn't even know one existed. Don't know if it is shipped on my > > machine, and don't know where to look for one. > > Oh boy, maybe I'll get to use GNU info! Not. Is there a hardcopy or html > > version somewhere? *sigh* > > Picky picky. The manual comes with the autoconf distribution tarball. > The master copy is in GNU "texinfo" format, looks like. I always use > the GNU-info-format version of it, which gets installed automatically > by autoconf's install script. But this is convenient for me because > I use the One True Editor, Emacs ;-) ;-). If you don't live in Emacs > then I agree info format is less than convenient. Actually, I just type 'info autoconf' on my machine(s) to read it...I don't use emacs myself, and don't find that 'info' requires fore-knowledge of it Marc G. Fournier Systems Administrator @ hub.org primary: scrappy@hub.org secondary: scrappy@{freebsd|postgresql}.org
> Actually, I just type 'info autoconf' on my machine(s) to read > it...I don't use emacs myself, and don't find that 'info' requires > fore-knowledge of it I'm info-impaired. Never used it enough to remember how to traverse it, and never managed to find what I needed without just running through the entire document. I'd like to learn emacs (I've got a new project using lisp) but haven't found it useful yet. 15 years of vi is tough to break. I suppose I should buy a book for it... - Tom
> > "Thomas G. Lockhart" <lockhart@alumni.caltech.edu> writes: > >> 8. There's really no substitute for reading the autoconf manual ;-). > > > Sure, didn't even know one existed. Don't know if it is shipped on my > > machine, and don't know where to look for one. > > Oh boy, maybe I'll get to use GNU info! Not. Is there a hardcopy or html > > version somewhere? *sigh* > > Picky picky. The manual comes with the autoconf distribution tarball. > The master copy is in GNU "texinfo" format, looks like. I always use > the GNU-info-format version of it, which gets installed automatically > by autoconf's install script. But this is convenient for me because > I use the One True Editor, Emacs ;-) ;-). If you don't live in Emacs > then I agree info format is less than convenient. There is also 'tkinfo' which makes reading info files fairly painless. -dg David Gould dg@illustra.com 510.628.3783 or 510.305.9468 Informix Software (No, really) 300 Lakeside Drive Oakland, CA 94612 - If simplicity worked, the world would be overrun with insects. -
Applied. Autoconf run. > Attached is a patch that uses autoconf to determine whether there is > a working 64-bit-int type available. > > In playing around with it on my machine, I found that gcc provides > perfectly fine support for "long long" arithmetic ... but sprintf() > and sscanf(), which are system-supplied, don't work :-(. So the > autoconf test program does a cursory test on them too. > > If we find that a lot of systems are like this, it might be worth > the trouble to implement binary<->ASCII conversion of int64 ourselves > rather than relying on sprintf/sscanf to handle the data type. > > regards, tom lane -- Bruce Momjian | 830 Blythe Avenue maillist@candle.pha.pa.us | Drexel Hill, Pennsylvania 19026 + If your life is a hard drive, | (610) 353-9879(w) + Christ can be your backup. | (610) 853-3000(h)