From: <no...@so...> - 2002-06-08 00:27:59
|
Feature Requests item #565088, was opened at 2002-06-05 16:33 You can respond by visiting: http://sourceforge.net/tracker/?func=detail&atid=360894&aid=565088&group_id=10894 Category: 48. Portability Support Group: None Status: Open Resolution: None Priority: 3 Submitted By: Joe English (jenglish) Assigned to: Joe English (jenglish) Summary: Bring tcl.h into the 1990s Initial Comment: Brief summary: <tcl.h> contains several preprocessor macros intended to aid source-level compatibility between ANSI C and K&R C compilers. However, the #ifdef logic tends to assume K&R C by default and enables modern features based on the presence of __STDC__ and/or other special cases. Since pre-ANSI compilers are a rarity nowadays (2002), and many compilers do not define __STDC__ in the default (non-strict-ansi) mode even though they do in fact support all the relevant features, it would make more sense to assume modern C by default and only enable the backwards-compatibility macros on a special-case basis. I'll put together a patch in the next couple of days. Detailed analysis (from a post to comp.lang.tcl): From: jen...@fl... (Joe English) Newsgroups: comp.lang.tcl Subject: Re: Build problem using aCC on HP-UX Date: 5 Jun 2002 15:32:02 GMT Message-ID: <adl...@en...> [...] The Tcl core was C89-compatible until the recent (8.4a2? 3?) addition of "long long", which is a C99 feature. (Actually, I'm not sure under which conditions 'long long' is actually used -- it's tough to decipher what's going on in the #ifdef chain in tcl.h). However, the core also includes backwards-compatibility #defines for several features which were not present in K&R C (VOID, CONST, USE_PROTOTYPE, USE_STDARG, etc.). The choice of whether to use C89 or K&R features is determined by whether or not __STDC__ is #define'd, or, in many cases, with an additional list of special cases, e.g. # if defined(__STDC__) || defined(__cplusplus) || defined(__BORLANDC__) Most compilers nowadays (in my experience) are C89, but do not yet fully support C99. Many of these support C9X features like "long long", but only when invoked in "extensions-enabled" mode. Here's where the problem comes up: "long long" is standard C99, but it's an extension to C89; thus 20th century compilers don't enable it in "strict ANSI" mode and Tcl 8.4 can't be compiled in that mode. Most compilers -- GCC being a notable exception -- don't define __STDC__ when extensions are enabled, so all of the backwards-compatibility cruft in tcl.h gets activated (except on platforms which have been accounted for by a special-case preprocessor test as above). The correct way to proceed is IMO to bring tcl.h into the 1990s: it should assume C89 features are present by default (void, const, stdarg.h, etc.), and only enable the backwards-compatibility cruft on a special-case basis, instead of the other way around. For example, instead of: #if ((defined(__STDC__) || defined(SABER)) && !defined(NO_PROTOTYPE)) \ || defined(__cplusplus) || defined(USE_PROTOTYPE) # define _USING_PROTOTYPES_ 1 # define _ANSI_ARGS_(x) x # define CONST const #else # define _ANSI_ARGS_(x) () # define CONST #endif use something like: #if defined(ANCIENT_COMPILER) # define CONST # define _ANSI_ARGS_(x) #else # define _ANSI_ARGS_(x) x # define CONST const #endif where ANCIENT_COMPILER is undefined by default. ---------------------------------------------------------------------- >Comment By: David Gravereaux (davygrvy) Date: 2002-06-07 17:27 Message: Logged In: YES user_id=7549 Could we put JOIN back? I've been known to use it such as in my expect-win32 port: /* * Version stuff. */ #define EXP_MAJOR_VERSION 6 #define EXP_MINOR_VERSION 0 #define EXP_RELEASE_LEVEL TCL_ALPHA_RELEASE #define EXP_RELEASE_SERIAL 0 #define EXP_VERSION STRINGIFY(JOIN (EXP_MAJOR_VERSION,JOIN(.,EXP_MINOR_VERSION))) #if EXP_RELEASE_LEVEL == TCL_ALPHA_RELEASE # define EXP_PATCH_LEVEL \ STRINGIFY( \ JOIN(JOIN (EXP_MAJOR_VERSION, \ JOIN(., EXP_MINOR_VERSION)), \ JOIN(a, EXP_RELEASE_SERIAL))) #elif EXP_RELEASE_LEVEL == TCL_BETA_RELEASE # define EXP_PATCH_LEVEL \ STRINGIFY( \ JOIN(JOIN (EXP_MAJOR_VERSION, \ JOIN(., EXP_MINOR_VERSION)), \ JOIN(b, EXP_RELEASE_SERIAL))) #elif EXP_RELEASE_LEVEL == TCL_FINAL_RELEASE # define EXP_PATCH_LEVEL \ STRINGIFY( \ JOIN(JOIN (EXP_MAJOR_VERSION, \ JOIN(., EXP_MINOR_VERSION)), \ JOIN(., EXP_RELEASE_SERIAL))) #else # include "bad/release/level/used" #endif ---------------------------------------------------------------------- Comment By: Joe English (jenglish) Date: 2002-06-07 15:47 Message: Logged In: YES user_id=68433 Also tested on Solaris 8/Workshop and Linux/Alpha/gcc (dgp), and, after a couple of go-arounds, on MSVC 6 (kkb). Patch 'take 6' should be OK. ---------------------------------------------------------------------- Comment By: Joe English (jenglish) Date: 2002-06-07 14:45 Message: Logged In: YES user_id=68433 One more time, this time with 'diff -c' instead of 'diff -u' ---------------------------------------------------------------------- Comment By: Joe English (jenglish) Date: 2002-06-07 14:31 Message: Logged In: YES user_id=68433 OK, patch attached. Tested on Linux (SuSE 6.3, gcc), HP-UX 10.20 (cc -Ae), and AIX 4 (native cc). ---------------------------------------------------------------------- Comment By: Joe English (jenglish) Date: 2002-06-07 08:40 Message: Logged In: YES user_id=68433 Other changes: In r1.8 of tcl.h, the definition of STRINGIFY: #define STRINGIFY(x) STRINGIFY1(x) #define STRINGIFY1(x) #x was replaced with a messy #ifdef chain. The current version uses the above (correct) definition when _MSC_VER or RESOURCE_INCLUDED is defined, an incorrect version if __STDC__ is defined, and a fourth version (which may or may not work on older compilers -- this wasn't possible to do portably pre-ANSI). It also added a JOIN() macro, which is not used anywhere in the core. STRINGIFY() appears in two places (win/tclWinPipe.c, win/tcl.rc). I plan to revert to the older definition. (On the tcl'ers chat, Jeff said this would be OK.) I also plan to remove references to <sys/type.h>: this was added as part of the TIP 72 implementation, but it turns out not to be needed (confirmed by DKF [private email], who added it initially), and causes problems compiling on non-POSIX systems. (<sys/types.h> is a POSIX header file that defines various typedefs like dev_t, pid_t, ino_t, etc., none of which are used elsewhere). ---------------------------------------------------------------------- Comment By: Joe English (jenglish) Date: 2002-06-07 07:56 Message: Logged In: YES user_id=68433 > [...] please avoid any macro like "ANCIENT_COMPILER". Naturally :-) Currently I'm using the following CPP symbols: NO_PROTOTYPES NO_CONST NO_VOID NO_STDARG All of which are undefined by default. This should allow the current build system to work unchanged on any modern compiler. As far as I can tell, all of the platforms mentioned in tcl.m4/configure.in, as well as Windows (MSVC, Borland C, GCC+CYGWIN, GCC+MINGW) and the Mac satisfy this criteria but please someone correct me if I'm wrong. I'm unable to test this patch on a pre-ANSI compiler, since I no longer have one available. ---------------------------------------------------------------------- Comment By: Don Porter (dgp) Date: 2002-06-07 07:33 Message: Logged In: YES user_id=80530 The basic idea seems fine, but please avoid any macro like "ANCIENT_COMPILER". By the time 2010 gets here, every compiler we're using now will be an "ancient compiler", but that's not what we mean. Use macro names that say precisely what they mean. ---------------------------------------------------------------------- Comment By: Donal K. Fellows (dkf) Date: 2002-06-07 02:44 Message: Logged In: YES user_id=79902 David: No. It increases the maintenance cost too much, and I am not convinced the benefits are worth it. If the new compilers cope with the source as it is now, there's no good reason to change it. Especially as I don't fancy typing all that stuff in every time I create a new function! And I think old style function defns are more readable anyway. It is one of the few places where ANSI, by tailing C++, did not improve things IMHO... ---------------------------------------------------------------------- Comment By: David Gravereaux (davygrvy) Date: 2002-06-06 18:07 Message: Logged In: YES user_id=7549 Bravo! How about we hit the source, too? int #if OLD_CRUFTY_PRE_ANSIC89_COMPILER Tcl_Stat(path, oldStyleBuf) CONST char *path; /* Path of file to stat (in current CP). */ struct stat *oldStyleBuf; /* Filled with results of stat call. */ #else Tcl_Stat( CONST char *path, /* Path of file to stat (in current CP). */ struct stat *oldStyleBuf) /* Filled with results of stat call. */ #endif { .... ---------------------------------------------------------------------- You can respond by visiting: http://sourceforge.net/tracker/?func=detail&atid=360894&aid=565088&group_id=10894 |