Ticket UUID: | 565088 | |||
Title: | Bring tcl.h into the 1990s | |||
Type: | RFE | Version: | None | |
Submitter: | jenglish | Created on: | 2002-06-05 23:33:17 | |
Subsystem: | 52. Portability Support | Assigned To: | jenglish | |
Priority: | 3 Low | Severity: | ||
Status: | Closed | Last Modified: | 2002-06-18 08:32:42 | |
Resolution: | Fixed | Closed By: | davygrvy | |
Closed on: | 2002-06-18 01:32:42 | |||
Description: |
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: [email protected] (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: <[email protected]> [...] 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. | |||
User Comments: |
davygrvy added on 2002-06-18 08:32:42:
Logged In: YES user_id=7549 adapted the rc files in Tcl and Tk to support the RC_INVOKED change and committed it. Thanks. hobbs added on 2002-06-18 05:54:47: Logged In: YES user_id=72656 just closing ... if problems, resurface, we know who to blame. ;) jenglish added on 2002-06-18 01:32:46: Logged In: YES user_id=68433 Patch committed (generic/tcl.h r1.125 -> r1.126), including davygrvy's RC_INVOKED changes below. Leaving this item open for now in case any problems surface. davygrvy added on 2002-06-08 10:28:31: File Added - 24665: more_tcl_h_Hunks.txt davygrvy added on 2002-06-08 10:28:30: Logged In: YES user_id=7549 works good on windows. Can I sneak a few hunks into the patch, or am I off-topic? This changes the Tcl specific use of RESOURCE_INCLUDED to be the proper RC_INVOKED as done by the windows rc compiler all on it's own. jenglish added on 2002-06-08 08:27:35: File Deleted - 24650: File Added - 24664: tcl.h.patch Logged In: YES user_id=68433 > Could we put JOIN back? Done. Patch version 7 uploaded. davygrvy added on 2002-06-08 07:27:57: 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))) #ifEXP_RELEASE_LEVEL == TCL_ALPHA_RELEASE #define EXP_PATCH_LEVEL \ STRINGIFY( \ JOIN(JOIN (EXP_MAJOR_VERSION, \ JOIN(., EXP_MINOR_VERSION)), \ JOIN(a, EXP_RELEASE_SERIAL))) #elifEXP_RELEASE_LEVEL == TCL_BETA_RELEASE #define EXP_PATCH_LEVEL \ STRINGIFY( \ JOIN(JOIN (EXP_MAJOR_VERSION, \ JOIN(., EXP_MINOR_VERSION)), \ JOIN(b, EXP_RELEASE_SERIAL))) #elifEXP_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 jenglish added on 2002-06-08 05:47:11: File Deleted - 24644: File Added - 24650: tcl.h.patch 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. jenglish added on 2002-06-08 05:18:53: File Added - 24644: tcl.h.patch jenglish added on 2002-06-08 04:58:11: File Deleted - 24641: File Added - 24642: tcl.h.patch jenglish added on 2002-06-08 04:50:14: File Deleted - 24640: File Added - 24641: tcl.h.patch jenglish added on 2002-06-08 04:45:12: File Added - 24640: tcl.h.patch Logged In: YES user_id=68433 One more time, this time with 'diff -c' instead of 'diff -u' jenglish added on 2002-06-08 04:31:37: File Added - 24639: tcl.h.patch 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). jenglish added on 2002-06-07 22:40:08: 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). jenglish added on 2002-06-07 21:56:00: 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. dgp added on 2002-06-07 21:33:43: 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. dkf added on 2002-06-07 16:44:21: 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... davygrvy added on 2002-06-07 08:07:48: 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 { .... |