Document number: ISO/IEC JTC 1/SC22 WG14 N821 (J11/98-020) ________________ beginning of title page _______________________________ ISO/IEC JTC 1/SC22 Programming languages, their environments and system software interfaces Secretariat: U.S.A. (ANSI) ISO/IEC JTC 1/SC22 N2690 TITLE: Summary of Voting on CD Approval of CD 9899 - Information technology - Programming languages - Programming Language C (Revision of ISO/IEC 9899:1990) DATE ASSIGNED: 1998-04-16 SOURCE: Secretariat, ISO/IEC JTC 1/SC22 BACKWARD POINTER: N/A DOCUMENT TYPE: Summary of Voting PROJECT NUMBER: JTC 1.22.20.01 STATUS: WG14 is requested to prepare a Disposition of Comments Report and a recommendation on the further processing of the CD. ACTION IDENTIFIER: FYI to SC22 Member Bodies ACT to WG14 DUE DATE: N/A DISTRIBUTION: Text CROSS REFERENCE: SC22 N2620 DISTRIBUTION FORM: Def Address reply to: ISO/IEC JTC 1/SC22 Secretariat William C. Rinehuls 8457 Rushing Creek Court Springfield, VA 22153 USA Telephone: +1 (703) 912-9680 Fax: +1 (703) 912-2973 email: rinehuls@access.digex.net ____________ end of title page; beginning of overall summary __________=20 SUMMARY OF VOTING ON Letter Ballot Reference No: SC22 N2620 Circulated by: JTC 1/SC22 Circulation Date: 1997-12-24 Closing Date: 1998-04-07 SUBJECT: =20 CD Approval of CD 9899: Information technology - Programming languages - Programming Language C (Revision of ISO/IEC 9899:1990) ---------------------------------------------------------------------- The following responses have been received on the subject of approval: "P" Members supporting approval without comment 5 "P" Members supporting approval with comment 1 "P" Members not supporting approval 4 "P" Members abstaining 2 "P" Members not voting 10 "O" Members supporting approval without comment 1 ------------------------------------------------------------------------ Secretariat Action: =20 WG14 is requested to prepare a Disposition of Comments Report and make a recommendation on the further processing of the CD. The comments accompanying the affirmative vote from Canada and the negative votes from Denmark, France, Japan and the United Kingdom are attached. In addition to the comments accompanying the votes from SC22 Member Bodies, Switzerland submitted comments which are also attached for WG14 consideration. The comment accompanying the abstention vote from Germany was: "There is no national rapporteur or committee for C." ________ end of overall summary; beginning of detailed summary ________ ISO/IEC JTC1/SC22 LETTER BALLOT SUMMARY PROJECT NO: JTC 1.22.20.01 SUBJECT: CD Approval of CD 9899: Information technology - Programming languages - Programming Language C (Revision of ISO/IEC 9899:1990= ) =20 Reference Document No: N2620 Ballot Document No: N2620 Circulation Date: 12-24-1997 Closing Date: 04-07-1998=20 =20 Circulated To: SC22 P, O, L Circulated By: Secretariat SUMMARY OF VOTING AND COMMENTS RECEIVED Approve Disapprove Abstain Comments Not Voting 'P' Members Australia ( ) ( ) (X) ( ) ( ) Austria ( ) ( ) ( ) ( ) (X) Belgium ( ) ( ) ( ) ( ) (X) Brazil ( ) ( ) ( ) ( ) (X) =20 Canada (X) ( ) ( ) (X) ( ) China ( ) ( ) ( ) ( ) (X) Czech Republic (X) ( ) ( ) ( ) ( ) Denmark ( ) (X) ( ) (X) ( ) Egypt ( ) ( ) ( ) ( ) (X) Finland (X) ( ) ( ) ( ) ( ) France ( ) (X) ( ) (X) ( ) Germany ( ) ( ) (X) (X) ( ) Ireland ( ) ( ) ( ) ( ) (X) Japan ( ) (X) ( ) (X) ( ) Netherlands (X) ( ) ( ) ( ) ( ) Norway (X) ( ) ( ) ( ) ( ) Romania ( ) ( ) ( ) ( ) (X) Russian Federation ( ) ( ) ( ) ( ) (X) Slovenia ( ) ( ) ( ) ( ) (X) UK ( ) (X) ( ) (X) ( ) Ukraine ( ) ( ) ( ) ( ) (X) USA (X) ( ) ( ) ( ) ( ) 'O' Members Voting Korea Republic (X) ( ) ( ) ( ) ( ) In addition, Switzerland submitted comments. ________ end of detailed summary; beginning of Canada comments ______ Canada Vote on CD Ballot: Approve with comments Comments: Comment #1 Category: Normative Committee Draft subsection: 6.2.1.2 Title: Converting to signed integral type Description: Section 6.2.1.2 paragraph 3 describes the result of converting a value with integral type to a signed type which cannot represent the value. It says that the result is implementation defined, however, we believe that the result should be undefined, analogous to the case where an operation yields a value which cannot be represented by the result type (Section 6.3, paragraph 5). Comment #2 Category: Normative Committee Draft subsection: 6.5.6 Title: VLAs and typedefs Description: The draft needs to clearly state when typedefs involving VLAs get evaluated. The current wording is confusing as it seems to imply that the size is evaluated at entry to the block instead of at the start of the scope of the typedef name. Comment #3 Category: Normative Committee Draft subsection: 6.5.5.2 Title: VLAs and side effects Description: In section 6.5.5.2, paragraph 3, the draft says, "It is unspecified whether side effects are produced when the size expression is evaluated". We believe that the behaviour should be specified, either that side effects take place or that they are disallowed and diagnosed at compile time. Comment #4 Category: Normative Committee Draft subsection: 7.1.6 Title: Width of ptrdiff_t Description: The width of ptrdiff_t should be required to be at least as large as the width of size_t. Comment #5 Category: Normative Committee Draft subsection: 6.5.4 Title: Static objects in inline function definitions Description: The restriction on static objects defined within an inline definition of a function with external linkage (section 6.5.4, paragraph 3) is not sufficient to allow the intended implementation strategy. Either the restriction should be corrected (allowing the simple implementation) or dropped (allowing an implementation to decide whether it can manage to inline any particular function). Comment #6 Category: Normative Committee Draft subsection: 6.5.4 Title: Linkage of inline definitions Description: The interaction between inline and linkage is not clear in the draft, and the specified syntax for creating an external function from an inline definition is not in the spirit of C. Comment #7 Category: Normative Committee Draft subsection: 7.4.3 Title: Macros for integer constants Description: The macros for integer constants defined in 7.4.3 seem to be redundant and hard to make robust. Consideration should be given to eliminating them. Comment #8 Category: Normative Committee Draft subsection: 6.3.2.5 Title: Scope of compound literals Description: The last paragraph of 6.3.2.5 (end of example 9, page 79) points out a highly undesirable property of compound literals: when the address of a compound literal is taken, correct usage is very sensitive to the exact placement of braces. It would seem that the utility of compound literals would not be greatly reduced if this were simply forbidden; their primary benefit would appear to be for the creation of compound *values*, not anonymous variables (C already has a way to create variables, after all). This restriction would also keep C clear of the C++ "lifetime of temporaries" swamp. There is already a C entity which has the desired properties: the return value of a function. Analogous rules would suffice for compound literals (and compound literals would fit into the existing language better that way). Basically, 6.3.2.5 paragraph 5 needs to be modified to delete the last sentence (ie. deny lvalue status to compound literals), and 6.3.2.5 needs to add a constraint analogous to 6.7.1 paragraph 3 (ie. type may not be an array, since there is nothing much that can be done with an array which doesn't involve taking its address). ____________ end of Canada comments; beginning of Denmark comments ____ Comments on SC22 N2620 CD ballot on C from Danish Standards Association The Danish vote is "no" with comments.=20 If the following comments can be accomodated, the Danish vote will be changed to "Yes". 7.3.2 There should only be one expected result for the=20 toupper() and tolower() functions, respectively. 7.5.2.1 int_curr_symbol different from currency_symbol As there may be differences between the order of how local currency is written and how international currency is written, it is proposed to=20 add the following members (none of which are part of the POSIX spec, but they are part of ISO/IEC FCD 14652) to the lconv struct, as follows: -------- Start Changed Section ---------- 7.5 Localization [#2]=09... =09char int_p_cs_precedes; /* CHAR_MAX */ =09char int_p_sep_by_space; /* CHAR_MAX */ =09char int_n_cs_precedes; /* CHAR_MAX */ =09char int_n_sep_by_space; /* CHAR_MAX */ =09char int_p_sign_posn; /* CHAR_MAX */ =09char int_n_sign_posn; /* CHAR_MAX */ -------- End Changed Section ---------- -------- Start Changed Section ---------- 7.5.2.1 The localeconv function [#3] ... char int_p_cs_precedes=09Set to 1 or 0 if the int_curr_symbol=20 respectively precedes or succeeds the value for a nonnegative formatted monetary quantity. char int_p_sep_by_space=09Set to 1 or 0 if the int_curr_symbol respectively is or is not separated by a space from the value for a nonnegative formatted monetary quantity. char int_n_cs_precedes=09Set to 1 or 0 if the int_curr_symbol respectively precedes or succeeds the value for a negative formatted monetary=20 quantity. char int_n_sep_by_space=09Set to 1 or 0 if the int_curr_symbol respectively is or is not separated by a space from the value for a negative=20 formatted monetary quantity. char int_p_sign_posn=09Set to a value indicating the positioning of the positive_sign for a nonnegative formatted monetary quantity. char int_n_sign_posn=09Set to a value indicating the positioning of the negative_sign for a negative formatted monetary quantity.=20 -------- End Changed Section ---------- In section 7.5.2.1 the examples need to be enhanced. =09There cannot be a point after ITL. =09Netherlands use a kind of small "f". =09Norway have at least a space between "kr" and the value. We need examples with all the new variables, int_p_cs_precedes etc. This is all done in the text below. -------- Start Changed Section ---------- 7.5.2.1 The localeconv function Examples [#8] The following table illustrates the rules which may well be used=20 by five countries to format monetary quantities. Country Positive format Negative format International format Italy L.1.234 -L.1.234 ITL 1.234 Netherlands f 1.234,56 f -1.234,56 NLG 1.234,56 Norway kr 1.234,56 kr 1.234,56- NOK 1.234,56 Switzerland SFrs.1,234.56 SFrs.1,234.56C CHF 1,234.56 Finland 1.234,56 mk -1.234,56 mk FIM 1.234,56 [#9] For these five countries, the respective values for the monetary=20 members of the structure returned by localeconv are: Italy Netherlands Norway Switzerland Finland int_curr_symbol "ITL " "NLG " "NOK " "CHF " "FIM " currency_symbol "L." "f" "kr" "SFrs." "mk" mon_decimal_point "" "," "," "." "," mon_thousands_sep "." "." "." "," "." mon_grouping "\3" "\3" "\3" "\3" "\3" positive_sign "" "" "" "" "" negative_sign "-" "-" "-" "C" "-" int_frac_digits 0 2 2 2 2 frac_digits 0 2 2 2 2 p_cs_precedes 1 1 1 1 0 p_sep_by_space 0 1 0 0 1 n_cs_precedes 1 1 1 1 0 n_sep_by_space 0 1 0 0 1 p_sign_posn 1 1 1 1 1 n_sign_posn 1 4 2 2 1 int_p_cs_precedes 1 1 1 1 1 int_p_sep_by_space 0 1 0 0 1 int_n_cs_precedes 1 1 1 1 1 int_n_sep_by_space 0 1 0 0 1 int_p_sign_posn 1 1 1 1 1 int_n_sign_posn 1 4 2 2 4 -------- End Changed Section ---------- 7.4.2.1 p_sep_by_space and n_sep_by_space POSIX has added a third possibility for a formatted monetary quantity,=20 so now we have: =09No space separates the currency_symbol from the value. =09A space separates the symbol from the value. *New*=09A space separates the symbol and the value, if these entities are= =20 next to eachother. The new parameter is required to properly display monetary amounts in Denmark and a number of other European countries. For example the format "DKK -1.234,56" is very common and not doable with the current C standard. -------- Start Changed Section ---------- 7.5.2.1 The localeconv function [#3] ... char p_sep_by_space=09Set to 0 if no space separates the currency_symbol from the value for a nonnegative formatted monetary quantity; set to 1 if a space separates the symbol from the value; and set to 2 if a space separates the symbol and the value, if adjacent. char n_sep_by_space=09Set to 0 if no space separates the currency_symbol from the value for a negative formatted monetary quantity; set to 1 if a space separates the symbol from the value; and set to 2 if a space separates the symbol and the value, if adjacent. char int_p_sep_by_space=09Set to 0 if no space separates the int_curr_symbo= l from the value for a nonnegative formatted monetary quantity; set to 1 if a space separates the symbol from the value; and set to 2 if a space separates the symbol and the value, if adjacent. char int_n_sep_by_space=09Set to 0 if no space separates the int_curr_symbo= l from the value for a negative formatted monetary quantity; set to 1 if a space separates the symbol from the value; and set to 2 if a space separates the symbol and the value, if adjacent. -------- End Changed Section ---------- ---------------- added section in rationale ----------------- This section should go into the rationale A table giving example formats for the combinations of p_cs_precedes, p_sign_posn and p_sep_by_space is given below, given that the positive_sign is "+" and the currency_symbol is "$".=20 p_sep_by_space 2 1 0 p_cs_precedes =3D 1 p_sign_posn =3D 0 ($ 1.25) ($ 1.25) ($1.25) p_sign_posn =3D 1 + $1.25 +$ 1.25 +$1.25 p_sign_posn =3D 2 $1.25 + $ 1.25+ $1.25+ p_sign_posn =3D 3 + $1.25 +$ 1.25 +$1.25 p_sign_posn =3D 4 $ +1.25 $+ 1.25 $+1.25 p_cs_precedes =3D 0 p_sign_posn =3D 0 (1.25 $) (1.25 $) (1.25$) p_sign_posn =3D 1 +1.25 $ +1.25 $ +1.25$ p_sign_posn =3D 2 1.25$ + 1.25 $+ 1.25$+ p_sign_posn =3D 3 1.25+ $ 1.25 +$ 1.25+$ p_sign_posn =3D 4 1.25$ + 1.25 $+ 1.25$+ ------------------------------------------------------------------ 7.14.3.5 strftime The date utility in POSIX-2 4.15 and the strftime() function from the Open Group Single Unix Specification has all of the formats of C's strftime() plus more, all of which are proposed to be added to strftime(), ie merged with the current list: %C is replaced by the year divided by 100 and truncated to an integer, as a decimal number (00-99) %D is replaced by the date in the format mm/dd/yy %e is replaced by the day of the month as a decimal number (1-31 in a two-digit field with leading fill) %h a synonym for %b %n is replaced by a character %r is replaced by the 12 h clock time (01-12) using the AM/PM notation; in the "C" locale, this shall be equivalent to "%I:%M:%S %p" %R is replaced by the time in 24 hour notation (%H:%M) %t is replaced by a character A number of modified field descriptors %O and %E are also defined in POSIX.2 (4.15.4.2) or in The Open Group's strftime() definition. Text to be added for the C standard, after the "%%" definition: Some field descriptors can be modified by the E and O modifier characters to indicate a different format or specification as specified in the LC_TIME locale description. If the corresponding data (see era, era_year, era_d_fmt, and alt_digits) is not specified or not supported for the current locale, the unmodified field descriptor value shall be used. %Ec Locale's alternate date and time representation. %EC The name of the base year (period) in the locale's alternate representation. %Ex Locale's alternate date representation. %EX Locale's alternate time representation. %Ey Offset from %EC (year only) in the locale's alternate representation. %EY Full alternate year representation. %Od Day of month using the locale's alternate numeric symbols. %Oe Day of month using the locale's alternate numeric symbols. %OH Hour (24-hour clock) using the locale's alternate numeric symbols. %OI Hour (12-hour clock) using the locale's alternate numeric symbols. %Om Month using the locale's alternate numeric symbols. %OM Minutes using the locale's alternate numeric symbols. %OS Seconds using the locale's alternate numeric symbols. %Ou Weekday using the locale's alternate numeric symbols=20 (Monday=3D1). %OU Week number of the year (Sunday as the first day of the week) using the locale's alternate numeric symbols. %OV Week number using the locale's alternate numeric symbols, using rules corresponding to %V. %Ow Weekday as number in the locale's alternate representation (Sunday=3D0). %OW Week number of the year (Monday as the first day of the week) using the locale's alternate numeric symbols. %Oy Year (offset from %C) in alternate representation. -------------------------------------------------- Basic addressing of I/O hardware support should be included in C9X, as I/O addressing support in C is of major importance for=20 the market for free-standing environments. Denmark believe that having support for I/O addressing in C will be a great benefit for both the individual programmer, the individual=20 company, and the electronic industry as a whole. By adding I/O addressing support in C9x as an optional annex, as proposed in N731, the requirements from the market for free-standing environments = =20 can be fulfilled, without any inconvenience for those compilers for hosted= =20 environments which do not want to support I/O addressing. __________ end of Denmark comments; beginning of France comments ______ From: ARNAUD.A.R.D.DIQUELOU@email.afnor.fr - N2620 - CD Approval Ballot for CD 9899: C Programming Language France votes NO to document SC22 N2620. It will reverse its vote if the following comments are satisfactorily resolved. General comments: 1. Committee Draft subsections: many Category: Feature that should be removed (major technical) Title: Suppression of long long Rationale: In C90, the long type had two uses: - it was the longest integer type available (then by example its use at the preprocessor level), - it was the only integer type which warranted 32 bits. It also had the historical characteristics to be somewhat less slowly than type int, and to be used to represent offsets in files (classicaly the integral measure with the greatest magnitude). C9X try to extend the standard to permit the writing of programs handling 64 bits quantities; therefore, this will destroy (at least) one of the above assertions. Experience shows that in these cases, one should not extrapolate from existing features, but rather create a new, heathly mechanism. This had be done in C9X, and the result is the subclause 7.4 (the header). This clearly distinguish integer types having a known width from the types named [u]intmax_t, which are accompanied by functions strtoimax, strtoumax, wcstoimax and wcstoumax. Unfortunately, the support for these types, and in particular [u]intmax_t, is scarse in the rest of the library. Instead, the proposed draft introduces a solution which have been implanted in a part of the market: aside from long, there is a new integer type, long long, which is warrantied to be (at least) 64 bits long; and a number of new library functions to help dealing with this new type (atoll, llabs, lldiv, llrint, llround, strtoll, strtoull, wcstoll, wcstoull), and a new "ll" modifier to integer convertions with *printf and *scanf. correctly does the difference between the (at least) 64 buts long type and the longest type. long long and the proposed library functions do not, therefore the problem set up by long (2 signifiances) will not be solved by long long. In fact, it will lead programers to think long "is" 32 bits and long long "is" 64 bits... therefore making the very point of useless. Another defect is that while the historical need for "big" integer types is with file offsets, there is no long long equivalents for fseek and ftell. These functions, while superseeded by fsetpos and fgetpos in some uses, are still necessary (for example when the program calculate itself the offsets, or when the file have an externaly defined structure with internal "pointers"). Recommanded changes: From this analysis, we feel that: a) long long should be suppressed in the standard, but the door should be left opened for its use by the mean of the extended integer types in 6.1.2.5 (note 25 should be modified); b) direct and indirect obligations to the types described by the standard should be extended to all the extended integer types (this include lrint in 7.8, Annex F, and the modification below to subclause 7.4.4, point #18); c) [u]intmax_t should be always used when referencing the longest type (as it is already done in 6.8.2); d) new functions should be added to to do the equivalent of maxabs, maxdiv, fseekmax, ftellmax, maxrint and maxround (names are just indications). Side points: e) adding atoimax is more problematic, as the atol function is supposed to be superseeded by strtol. f) modifier "L" (or "m") could be used to handling integers of type [u]intmax_t with *printf and *scanf: this is not necessarily a good idea, as it would also need a modifier for size_t...) 2. Committee Draft subsections: 5.1.1.2, 5.2.1 Category: Request for information/clarification (major question) Title: Clarification of the status of UCN Rationale: 5.1.1.2p1, item 1, and 5.2.1p5 does not make clear if the notation \Unnnnnnnn consist of either 10 or 1 source character(s). Note 6 in 5.1.1.2 seems to imply it is only 1 character; however notes are not normative. If UCN are 10 characters long, there are a number of latent problems in 5.1.2, 6.1.3.4, 6.1.4, 6.1.7, 6.8.3.2, etc., most of them related with the special status of the \ character. We shall assume the correct reading is 1 character. We shall also assume that UCNs are full-right members of the character sets (they may need to be clarified in 5.2.1). There is also a change to be done in 5.1.1.2 to make this clear (see below, point #4). Also, a lot of place have not been updated with the appearance of UCNs. They should be rewritten accordingly (see below for details). Specific comments: 1. Committee Draft subsections: 4, 7.1, 7.4 Category: Normative change to intent of existing feature (minor technical) Title: Making available to freestanding implementations Rationale: Most of the content of subclause 7.4 (i.e. excluding 7.4.4 and 7.4.6) should be available for freestanding implementations. In fact, as those implementations are usualy "closer to the metal", they may more benefit from these changes like precisely-sized types than the hosted ones. However, the whole content of actual subclause 7.4 is not suitable for freestanding implementations. Proposed solution: A way to achieve it is to divide subclause 7.4 into two parts: a first one, containing the actuals subclauses 7.4 to 7.4.3 and 7.4.5, should be put in a new subclause 7.1.x preceding 7.1.6, and should be made mandatory to freestanding implementations (by updating clause 4). It should keep the existing title. The rest, i.e. 7.4.4 and 7.4.6, should be left as an independant subclause 7.x (while being moved, depending of the spelling of the corresponding header); it may be named (just a proposal). For strtoimax() and the like to be usefully used, it might be necessary to make the declaration of intmax_t also available in this new header. 2. Committee Draft subsection: 5.1.1.2 Category: Request for information/clarification (minor question) Title: locale to be used for source characters What is the locale to be used for the convertion of multi-byte source characters to UCN and then to execution characters? Should it be unspecified or implementation-defined? Or locale-specific (to permit strict conformance)? A reference in annexe K is also needed. Rationale: As it stands now, it is undefined for source characters, thus forbids any strictly conforming program with characters outer of the basic character set should be written with \u or \U. Is it as intended? 3. Committee Draft subsection: 5.1.1.2 Category: Normative change to existing feature retaining the original intent (minor technical) Title: Prohibit surrogates to being used as UCNs Rationale: 5.1.1.2p2 (Contraints) excludes some ranges to be used with UCNs. The range D000-DFFF (used for UTF-16, these values by themselves, named "surrogates", do not represent characters) should be excluded as well. Proposed solution: Exclude the range D000-DFFF as well. 3. Committee Draft subsection: 5.1.1.2 Category: Editorial change/non-normative contribution (minor editorial) Title: Consistency with ISO/IEC 10646 Proposed change: 5.1.1.2p2 (Contraints) specifies some range to be not used with UCNs. The references should be written in full (canonical) form, like 0000 0000= , 0000 0020, 0000 007F, 0000 009F (and 0000 D000, 0000 DFFF). 4. Committee Draft subsections: 5.1.1.2 Category: Normative change to intent of existing feature (major technical) Title: Clarification of the status of UCN Rationale: 5.1.1.2p1, item 1, and 5.2.1p5 does not make clear if the notation \Unnnnnnnn consist of either 10 or 1 source character(s). Note 6 in 5.1.1.2 seems to imply it is only 1 character; however notes are not normative. Proposed solution: If "1 character" is the correct reading, then a sentence should be added to 5.1.1.2 to specify that the sequence of 10 source characters {\}{U}{n}{n}{n}{n}{n}{n}{n}{n} should be transformed in one character (during translation phase 1). 5. Committee Draft subsection: 5.2.1 Category: Editorial change/non-normative contribution (minor editorial) Title: Consistency with ISO/IEC 10646 Proposed change: In 5.2.1p5, the reference to the Standard should be ISO/IEC 10646, without specifying the 1st part. This way, one could safely uses characters outside BMP when they will be defined. 6. Committee Draft subsection: 5.2.1 Category: Inconsistency (minor technical) Title: Are UCN part of the basic character set? Rationale: 5.2.1p1, last sentence should written another way. As it stands now, =09=09=09=09=09=09=09=09=09=09=09=09=09 any additional members beyond those required by this subclause are locale- specific. Given the fact that the UCN notation is described in this very subclause, and that it includes all the characters in ISO/IEC 10646, the present writing is somewhat useless. See also below an implication for 6.8p4. Proposed change: Move the UCNs (5.1.2p4-5) to another (new) subclause to highlight the difference between the basic and the extended character sets. 7. Committee Draft subsection: 5.2.1 Category: Inconsistency (minor editorial) Title: Clarification of the status of UCN Proposed change: In 5.2.1p3, the last sentence should be deleted. It says: If any other characters are encountered in a source file (except in a character constant, a string literal, a header name, a comment, or a preprocessing token that is never converted to a token), the behavior is undefined. Another possibility is to add identifer to the list of items. 8. Committee Draft subsection: 5.2.1.1 Category: Editorial change/non-normative contribution (minor editorial) Title: Correct designation of a national standard Rationale: 5.2.1.1, note 12, references "the ASCII code set". In the context of an International Standard, it should be for example "the US ASCII code set". Proposed change: Add "US". 9. Committee Draft subsection: 5.2.1.2 Category: Inconsistency (minor editorial) Title: Handling of UCNs into identifiers Rationale: In 5.2.1.2p2, in the two first items, "identifier" should be added to the lists. They also may be considered now useless, as shift states have been removed in translation phase 1, and hence all multibyte characters are valid (or the source will be rejected at translation phase 1). Proposed changes: - An identifier, comment, string literal, character constant, or header name shall begin and end in the initial shift state. - An identifier, comment, string literal, character constant, or header name shall consist of a sequence of valid multibyte characters. 10. Committee Draft subsection: 5.2.2 Category: Normative change to existing feature retaining the original intent (minor technical) Title: Making character display semantics in line with MSE Rationale: 5.2.2p1, first sentence, describes the `active position' in relation with fputc: [#1] The active position is that location on a display device where the next character output by the fputc function would appear. It should be `the fputc or fputwc functions' instead. Similarly, the next sentence describes a `printable character' as being defined by isprint: The intent of writing a printable character (as defined by the isprint function) to a display device [...] It should be `as defined by the isprint or iswprint functions' instead. 11. Committee Draft subsections: 6.1.3.4, 6.1.4 Category: Inconsistency (minor technical) Title: Making string litterals in line with character constants Rationale: The rules for the building of wide character constants and string literals are non consistent. 6.1.3.4p11 says, in part: The value of a wide character constant containing a single multibyte character that maps to a member of the extended execution character set is the wide character (code) corresponding to that multibyte character, as defined by the mbtowc function, with an implementation-defined current locale. The value of a wide character constant containing more than one multibyte character, or containing a multibyte character or escape sequence not represented in the extended execution character set, is implementation-defined. On the other hand, 6.1.4p5 says: for wide string literals, the array elements have type wchar_t, and are initialized with the sequence of wide characters corresponding to the multibyte character sequence. Proposed solution: The latter should be reworded to the following: for wide string literals, the array elements have type wchar_t, and are initialized with the sequence of wide characters corresponding to the multibyte character sequence, as defined by the mbstowcs function, with an implementation- defined current locale. The value of a wide string literal containing multibyte characters or escape sequences not represented in the extended execution character set, is implementation-defined. Also note that if a change is done to 6.1.3.4p11 to include universal character names in the list of items that may lead to implementation-defined behavior, the same change should be made to the proposed text accordingly. 12. Committee Draft subsection: 6.1.7 Category: Inconsistency (minor editorial) Title: Handling of UCNs into an example Proposed change: 6.1.7p4, last example, should be {#}{define} {const}{.}{member}{\U00000040}{\U00000024} 13. Committee Draft subsection: 6.1.9 Category: Inconsistency (minor editorial) Title: Handling of multibytes during preprocessing Rationale: 6.1.9p2, last sentence. There should be no need to examine the comments to find multibytes characters, as they are replaced by UCN during translation phase 1. Proposed solution: Remove the reference to multibytes. 14. Committee Draft subsection: 6.8 Category: Inconsistency (minor editorial) Title: Are UCN source characters? or escape sequences? or another thing? Proposed change: 6.8p4, replace [#4] In the definition of an object-like macro, if the first character of a replacement list is not a character required by subclause 5.2.1, then there shall be white-space separation between the identifier and the replacement list.122 with In the definition of an object-like macro, if the first character of a replacement list is neither a character required by subclause 5.2.1, nor an universal character name listed in Annex I, then there shall be white-space separation between the identifier and the replacement list.{122} The footnote then remains valid. Also note that the above modification (#6) must be made, as presently all UCNs are required by subclause 5.2.1 15. Committee Draft subsection: 6.8.3.3 Category: Inconsistency (minor editorial) Title: Are UCN source characters? or escape sequences? or another thing? Proposed change: 6.8.3.3p3, add before last sentence If the result of the concatenation is syntaxly identical to an UCN, the behavior is undefined. This will prevent the following example to be strictly conforming: #define paste(a,b) a ## b #define mkstr1(s) #s #define mkstr(s) mkstr1(s) char value[] =3D mkstr(paste(\u, 0024)); as it will fool a number of implementations using preprocessors. 16. Committee Draft subsection: 6.8.8 Category: Other: Addition of a new feature (minor technical) Title: New conditionaly predefined macro name __STDC_ISO_10646__ Rationale: While C9X adds support for all the universal character names in identifiers, there is currently no requisite to an implementation for the extended set of character to represent the whole set defined in ISO/IEC 10646:1993, and furthermore no conforming way for a program to learn if the type wchar_t could be used for this purpose. This point intends to solve this problem. Proposed solution: By defining a new constant named __STDC_ISO_10646__, the implementation will indicate that the values of type wchar_t are suitable to represent the elements of the universal character set defined in ISO/IEC 10646; as an example, in this case, L'A' will be guaranteed to be equal to 0x0041u. Furthermore, as ISO/IEC 10646 is an evolving standard, the value of the predefined macro should reflect the level ISO/IEC implemented, by the same mechanism as used by __STDC_VERSION__, i.e. by specifiying the year and month of the registration of the lastly supported amendment (so support of ISO/IEC 10646:1993 up to Am.9, which is the last one issued now, will be showed by defining the macro as 199712L). This can be done by adding a new item to the list in 6.8.8p2, which reads as: =09 __STDC_ISO_10646__ A decimal constant of the form YyyyMmL =09 (for example 199712L), intended to indicate that the values =09 of the type wchar_t (as defined in the header) =09 are the coded representations of the characters defined =09 by ISO/IEC 10646 (Universal Multiple-Octet Coded Character =09 Set, UCS), to the level specified by this standard with =09 all amendments applied up to the month "Mm" of the year =09 "Yyyy". A better wording can perhaps being found. Another solution (similar to the one used for floating-point support) is to include a new normative annex, and to require in this annex the specifications of Unicode (regarding classification of characters) and of ISO/IEC FCD 14652 (regarding collation of strings made of UCS characters). 17. Committee Draft subsection: 7.1, 7.17 Category: Editorial change/non-normative contribution (minor editorial) Title: Moving to a more logicial position Rationale: 7.17, Alternative spellings , is nowadays positionned after its established position coming from Am.1:1996 to ISO/IEC 9899:1990, i.e. after the subclause. This is now illogical, as (also required for freestanding implementations) have been put in subclause 7.1, and as the new header introduced by C9X have been put in their logical position regarding the alphabetic order (which is not the case for ). Proposed solution: Subclause 7.17 should be moved to a new subclause 7.1.x before 7.1.6 . 18. Committee Draft subsection: 7.4.4 Category: Inconsistency (minor technical) Title: Allow other convertions modifiers to be used in 7.4.4 Rationale: 6.1.2.5 introduces the new concept of "extended integer types", which can exist beyond char, short, int, long and long long. Unfortunately, 7.4 specifies that modifiers corresponding to the defined types should be those described by the standard ("hh", "h", "l" and "ll") therefore forbiding a implementation to define the types in as one of the extented types. Proposed solution: Remove the restriction. 19. Committee Draft subsection: 7.19.7.1.2 Category: Inconsistency (minor technical) Title: Making positive the non-error return value of wctob Rationale: 7.19.7.1.2, the wctob function, does not describe the sign convention of the single-byte representation returned. In particular, 7.19.7.1.2p3 say= s: Otherwise, it returns the single-byte representation of that character. Proposed solution: It should be written as Otherwise, it returns the single-byte representation of that character, as an unsigned char converted to an int. (This is copied from the description of fgetc). Note this is a quiet change from ISO/IEC 9899:1990/Am.1:1996 (existing implementations where char are signed may have chosen to return negative values; the new behavior can lead to overflow problems). ______ end of France comments; beginning of Japan comments ________ CD Approval Ballot for CD 9899: Information technology - Programming languages -=20 Programming Language C (revision of ISO/IEC 9899:1990) ---------------------------------------------------------- The National Body of Japan disapproves ISO/IEC JTC1/SC22 N 2620, "CD Approval Ballot for CD 9899: Information technology - Programming languages - Programming Language C (revision of ISO/IEC 9899:1990)" for reasons below. 1. Technical Comments --------------------- Japan has been having some technical comments which were submitted to SC22 at the CD registration ballot. WG14 made the disposion paper (SC22 N2618) for these comments.=20 However, Japan can not agree with some of WG14's dispositions. Section 3 in this paper describes such a kind of open issues (including editorial comments). As for technical issues, please refere subsection 3.1 through 3.3: - 3.1 The 64 bit data type should be optional - 3.2 The function atoll() is redundant as the ISO C language standard - 3.3 Example of ## operator 1.1 Multibyte characters in source file @ Subclause "5.1.1.2 Translation phases" Page 8-9, line 4-6 in paragraph 1: > Any multibyte source file character not in the basic > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=20 > source character set is replaced by the > ~~~~~~~~~~~~~~~~~~~~ > universal-character-name that designates that multibyte > character. This description reads that *ALL* of conforming implementations should replace *ANY* MULTIBYTE CHARACTERS IN THE SOURCE FILE to universal-character-name. If this is true, we have three questions below: 1) This rule says that any Japanese Kanji Characters in the source file should be replaced to universal-character-name by *ANY* implementations EVEN IF THEY ARE MADE IN US. Is this the intention of SC22/WG14? (We do not think so.) 2) Does the ISO C standard prohibit an implementation from supporting multibyte character as the source character set which are NOT defined in the Annex I "Universal character names for identifiers"? (We do not think this is SC22/WG14's intention.) 3) This rule says that *ALL* of conforming implementations must have the conversion table between physical multibyte characters and a full set of universal-character-name defined in Annex I. The table must be very big. That is, the conforming implementation must be very fat. It is not welcome to users. Is this the intention of SC22/WG14? (We do not think so.) So, the above description should be changed to more precise sentence by using well-defined terms: > Then, the member of the extended character set of the > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > source which is not in the basic source character set may > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > be replaced by the universal-character-name that > designates that extended source character set members. 2. Editorial Comments --------------------- 2.1 Multibyte characters in source file @ Subclause "5.1.1.2 Translation phases" Page 8, Line 3-5 in paragraph 1: > 1. Physical source file multibyte characters are mapped to > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > the source character set ... if necessary. > Any multibyte source file character not in the basic > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > source character set is... Wording "Physical source file multibyte characters" and "multibyte source file character" are slightly unintelligible.=20 > Any source file multibyte character not in the basic > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > source character ... makes clearer. 2.2 Wrong reference to Annex I @ Subclause "6.1.2 Identifier" Page 34, line 4 in paragraph 2: "Annex H" should be corrcted to "Annex I". 2.3 "Function-sepcifiers" should be "function-specifier" @ Subclause "6.5 Declarations" Page 100, line 7 in paragraph 1: Syntactic category "function-sepcifiers" should be the same as "function-specifier" which is defined in "6.5.4 Function specifiers" (Page 116). Threfore, "function-sepcifiers" should be changed to "function-specifier". Annex B2.2 (page 444) should be corrected similarly. 2.4 "Function-sepcifiers" should be followed by other syntactic category @ Subclause "6.5 Declarations" Page 100, line 7 in paragraph 1: Syntactic category "function-sepcifiers" is defined alone. So, the C user cannot write other "declaration-specifiers" following it. It should be followed by "declaration-specifiers opt". Annex B2.2 (page 444) should be corrected similarly.=20 2.5 Wrong sentence in Tags @ Subclause "6.5.2.3 Tags" Page 108, line 2 in paragraph 3: "The type is complete" should be corrcted to=20 "The type is incomplete". 2.6 The behavior of "rewrite" should be clarified. @ Subclause "6.5.5.3 Function declarators(including prototypes)" Page 123, line 1 in paragraph 4: The term "rewrite" in the description: "After all rewrites, the parameters in a parameter-type-list that is part of a function definition shall not have incomplete type." is not defined anywhere. The behavior of "rewrite" should be clarified. 2.7 Examples for VLA is needed @ Subclause "6.5.6 Type names" Page 127, paragraph 3: The definitions of variable length array (VLA) are added in the syntax of the subclause 6.5.6. But any examples of VLA does not exist. Threfore, the examples of VLA should be added if possible like subclause 6.5.5.2 and 6.5.5.3. 2.8 "Declaration-list" should be defined @ Subclause "6.7.1 Function definitions" Page 150, line 2 in paragraph 1: In draft 11, "declaration-list" was dropped, because "block-item-list" was newly defined in "6.6.2 Compound statement, or block" (page 140) instead of "declaration-list" and "statement-list". It should be defined in 6.7.1 or elsewhere. Annex B2.4 (page 448) should be corrected similarly. 2.9 Publised year of ISO/IEC 9899 mismatches @ Subclause "6.8.8 Predefined macro names" Page 171, footnote 128 > 128. The value in ISO/IEC 9899:1994 was 199409L. @ Annex A "Bibliography" 12. Page 434 > ISO/IEC 9899:1993, Programming languages -- C Which is correct? Please use the correct document name/year. 2.10 Garbage in postscript file @ Subclause "6.8.8 Predefined macro names" Pages 171, line 2 in paragraph 2: > 1912.nr:c 0u+000m'unu This line looks like an garbage in the post script file of CD. Please correct it. 2.11 Missing information from asert macro for the identifire __func__ @ Subclause "7.2.1.1 The assert macro" Page 183, line 3-6 in paragraph 2: The information about the identifire __func__ should be added to the contents of the information written by asert macro. 2.12 Unnecessary description of C++ implementations @ Subclause "7.4.2 Limits of specified-width integer types" Page 193, footnote 149: @ Subclause "7.4.3 Macros for integer constants" Page 195, footnote 150: @ Subclause "7.4.4 Macros for format specifiers" Page 196. footnote 151: What is the intention of using the term "C++ implementations" in the footnote 149, 150, and 151 ? They should be removed from the specification of the C standard. 2.13 Place of reference to the footnote 153 @ Subclause "7.5 Localization " Page 202, line 1 in paragraph 3: It seems that the place of the reference to the footnote 153 is wrong (but, Japan is not so convinced whether or not it is wrong.) > The macros defined are NULL (described in 7.1.6); > and 153 +--+-> Is this place right? =20 Please make clear. 2.14 Defintions for float and long double math functions @ Subclause "7.7 Mathematics " Page 218, paragraph 1: @ Subclause "7.7.11.3 The nextafter function" Page 242 @ Subclause "7.7.11.4 The nextafterx function" Page 243, paragraph 2: In subclause 7.7, only "double" version mathematics functions are defined, and a definition of its "float" and "long double" version is derived by applying the rule described below: =09there are functions with the same name but with f =09and l suffixes which are corresponding functions =09with float and long double arguments and return =09values. But, every declaration for the "float" and "long double" version should be explicitly written in subclause 7.7, because the definition of some functions which have multiple arguments can not be derived according to the above rule. One expample is shown below. The "nextafer" function has two double parameters. =09double=09=09nextafter(double, double); But the type of second parameter of its "float" and "long double" versions, "nextaferf" and "nextaferl", are ambigious. According to the definition of "float" and "long double" versions, second parameter may have type "float" and "long double" respectively, such as in Annex D.9(page 465). =09float=09=09nextafterf(float, float); =09long double=09nextafterl(long double, long double); On the other hand, the "nextafterx" function is defined as follows =09The nextaferx function is equaivalent to the nextafrer =09function except that the second parameter has type long =09double. In this case, the type of second parameter has only type "long double".=20 According to this definition, type of second parameter of the "nextafter" function may have only the type "double". =09float=09=09nextafterf(float, double); =09long double=09nextafterl(long double, double); Which declarations of nextafter are correct? It is ambigious. 2.15 Necessary rationale for the changes of some environmental limits @ Subclause "7.13.6.1 The fprintf function" Environmental limit Page 293, line 2 in paragraph 14: The minimum value for the maximum number of characters produced by any single conversion is changed from 509 (in the current ISO/IEC 9899) to 4095. And also, some of other environmental limits are changed from ISO/IEC 9899. Please describe a clear rationale for these changes. 2.16 Wrong notation in the example of fprintf/fscanf for multibyte characters=20 1) @ Subclause "7.13.6.1 The fprintf fumction" Examples Page 294, line3 in paragraph 16: @ Subclause "7.13.6.2 The fscanf functin" Examples 1,2,3,4=20 Page 302, line 3 in paragraph 18: Two character (or, two byte) notation "$0" is used to represent the first byte of a multibyte character. However, in the original Amendment 1, a *single* square mark is used for this purpose in order to clearly represen that it is just *one* byte. =20 Please use one byte notation to represent the first byte of a multibyte character. 2) @ Page 294, paragraph 19: The printed image of the example of fprintf is NOT correct because the two byte notation $0 is used to represent one byte. That is, positions of the right hand side vertical bars are not aligned at the same column. They should be printed in the same column. Please use one byte notation to represent the first byte of a multibyte character. 2.17 Wrong conversion specifier in the example of fprintf @ Subclause "7.13.6.1 The fprintf function" Examples Page 294, line 6 in paragraph 18: "%13.1ls" should be corrected to "%13.11ls". (The original Amendment 1 has the same mistake.) 2.18 The bahavior of a successful call to fseek and fsetpos @ Subclause "7.13.9.2 The fseek function" Page 317, paragraph 5: @ Subclause "7.13.9.3 The fsetpos function" Page 317, paragraph 3: The description about the behavior of a successful call to the fseek function was made clear in the current CD (SC22 N2620). However, the description of fsetpos about a successful call was not changed from the ISO/IEC 9899. The behavior of successful call to fseek should be same as fsetpos. Please update the description about the behavior of a successful call to fsetps in the same way of fseek. 2.19 The redundunt sentences in mktime() @ Subclause: 7.16.2.3 The mktime function page 360, paragraph 3-6: The lst sentence in the paragraph 5 and all sentences in the paragraph 6 are entirely the same as all sentences of the paragraph 3 and 4. The last sentence in paragraph 5 and all sentences in paragraph 6 should be dropped. 2.20 Missng iswblank() in the description of iswctype() @ Subclause "7.18.2.2.2 The iswctype function" Page 377, paragraph 3: Please add "iswctype(wc, wctype("blank")) // iswblank(wc)" 2.21 Incorrect parameter type of the nextafterx function @ Annex "D.9 Mathematics " Page 465, line 15-16: The "nextafterxf" and "nextafrerxl" functions are declared as follows. =09float=09=09nextafterxf(float, long float); =09long double=09nextafterxl(long double, long long double); Each second parameter shall have type "long double". 2.22 Descriptions for some functions are not found @ Annex "F.9.3 Exponential and logarithmic functions" Page 499-501:=20 A description for "scalbln" function is not found. @ Annex "F.9.6 Nearest integer functions" Page 503-505: A description for "llrint" and "llround" functions are not found. @ Annex "F.9.8 Manipulation functions" Page 506: A description for "nextafterx" function is not found. 2.23 No more "common warning" @ Annex "J Common Warnings" Page 530, paragraph 2: Following warning is no more "common warning". =09- A function has return statements with and without =09 expressions. In subclause 6.6.6.4 Return statement(page 147), "Constrains" has been changed from previous draft and the following second sentence is appended: =09A return statement with an expression shall not =09appear in a function whose return type is void. =09A return statement without an expression shall only =09appear in a function whose return type is void. This means a function shall not have return statements both with and without expression. It is an undefined behavior. 2.24 Incomplete Annex K Portability issues=20 @ "Annex K Portability issues" Page 532-554 Undefined/unspecified/implementation-defined behaviors descreibed in "Amendment 1" are not included in the Annex K1-K3. Please add the summary of them to Annex K1-K3. 3. Further Comments on SC22 N2618 --------------------------------- Japan has further comments on some of SC22/WG14's dispositions described in SC22 N2618 (Disposition of Comments Report on CD Registration for CD 9899: Informationtechnology -=20 Programming languages - Programming Language C (Revision of ISO/IEC 9899:1993)). 3.1 The 64 bit data type should be optional > 1. Technical Comments > 1) Type long long int and lldiv_t should be optional. >=20 > Paragraph 1 of subclause 5.2.4.1 (page 19 in draft 9),=20 > paragraph 3 of subclause 6.1.2.5 (page 32 in draft 9),=20 > constraints of subclause 6.5.2 (page 83 in draft 9), and > paragraph 2 of subclause 7.13 (page 258 in draft 9): >=20 > Type (unsigned) long long int is introduced into the draft 9 > as a mandatory part of the standard C. The maximum and > minimum values for an object of type (unsigned) long long > int are defined in the subclause 5.2.4.2. These values need > to be represented by using 64 bit data type. Implementation > of type (unsigned) long long int, however, is too hard for > the compiler on the currently widely used 16 or 32 bit > architecture machines. The cross compiler on the small > machine must especially face a big difficulty when > implementing type (unsigned) long long int. Therefore, > type (unsigned) long long int should be a part of an=20 > optional specification or a part of the common extension of > the standard C. >=20 > A new type lldiv_t defined in subclause 7.13 should be > reconsidered as well as type long long int. >=20 > WG14: The Committee believes that the current WD is specifing current > pracitice. The Committee also believes that the benifit to the use= r > community out weights the cost of implementation for this feature. >=20 Japanese original comment is not proposing to drop the specification of the type long long int at all. Japanese comment does not intend "all-or-nothing" about long long int. Japan is just proposing that "the 64 bit data type" should be OPTIONAL, not mandatory. The above WG14's disposion does not seem to explain an appropriate reason to dispapprove "optional." Japan, of course, knows well that there are the users who need the 64 bit data type and also knows well it is possible to implement the 64 bit data type even on the 16 or 32 bit architecture machine even if it is a hard work, however, a population of the 64 data type users are NOT the whole of the C language user community. Japan thinks that there are still significant nubmers of users who must be in trouble with an unnecessary FAT implementation of the mandatory 64 bit data type. Actually, for example, there are lots of developers and vendors of small embeded system who are imposed to use or develop "the ISO C comforming implememtaion" by their customers/cliants or employers even if the 64 bit date is comletely unnecessary to develop their system. In this case, the 64 bit data type is just only a heavy burden for them. The implementation of 64 bit data type is not the benefit to this kind of users community at all. This is just one of the examples. So, Japan thinks that the words "the benifit to the user community" in WG14's disposition does not express the real situation. Correctly speaking, in the user community, there are people who get the benefit from the 64 bit data type, but, on the other hand, there are still a lot of people who feel a disadvantage in the fat implementation of the 64 bit data type. So, please reconsider to make the 64 bit datat type optional. (Japan does NOT mean to drop the long long int itself.) 3.2 The function atoll() is redundant as the ISO C language standard > 1. Technical Comments > 3) Function atoll() should be dropped. >=20 > Subclause 7.13.1.4 (page 260 in draft 9): >=20 > A new function atoll() is redundant for the standard C. > (Every ato*() functions can be replaced by strto*().) > The functions which can be directly replaced by other > functions should not be included in the standard C. Not > introducing redundant functions was one of the important > policies of development of the Amendment 1. This policy is > clearly described in the annex B.3 of the Amendment 1. If > the committee had determined to include the function atoll() > by some strong reason, why are NOT atod(), atold() included > in the draft 9? Please drop atoll() from the draft, or please > document a clear rationale which describes the reason why only > atoll() was added.=20 >=20 > WG14: The Committee discussed this, and believes that this feature > is currently existing practice. The consensus of the Committee > is that the simple interface of this function is usefull to the > user community. Japan can not agree a direct addition of extra function only by the simple reason "it is currently existing practice" and "the simple interface of it is useful to the user community." If "the simple interface is usefull to the user community" is so importnat, why atod() and atold() are not added? The atod() and atold() provide the simple interface to the user community as well as atoll(). It seems there is no policy and no criteria to make the language standard here. Introducing new ato*() to the ISO C standard is apparently break "the spirit of C" described in the Charter of C9X:=20 - Keep language small and simple - Provide only one way to do an operation Japan requests again here: Please drop atoll() from the draft, or please document a CLEAR RATIONALE which describes the reason why ONLY atoll() was added and the reason why other ato*() are NOT added.=20 Please make the criteria of intorduction of new functions clear. 3.3 Example of ## operator > 1. Technical Comments > 5) Illegal example of ## operator >=20 > Paragraph 4 (example) of subclause 6.8.3.3 (page 131 in > draft 9): >=20 > In the Example of the ## operator(paragraph 4 of > subclause 6.8.3.3 (page 131)), that is, > =09----------------------------------------------------- > =09=09=09#define hash_hash # ## # > =09=09=09#define mkstr(a) # a > =09=09=09#define in_between(a) mkstr(a) > =09=09=09#define join(c, d) in_between(c hash_hash d) >=20 > =09=09=09char p[] =3D join(x, y); /* equivalent to */ > =09=09=09=09 /* char p[] =3D "x ## y"; */ >=20 > =09 The expansion produces, at various stages: >=20 > =09 join(x, y) > =09 > =09=09 in_between(x hash_hash y) >=20 > =09 in_between(x ## y) ---- line (A) >=20 > =09=09 mkstr(x ## y) >=20 > =09 "x ## y" > =09----------------------------------------------------- > =20 > an object-like macro "hash_hash" is replaced by "##" at > line (A). Well then, what kind of preprocessing-token is > the "##" at line (A)?=20 >=20 > First, we can not find out any preprocessing-token other > than "operator" for ##, therefore, the ## at line (A) > must be the operator. Right? If so, the following > description in the example must be incorrect: > =09In other words, expanding hash_hash produces a new > =09token, consisting of two adjacent sharp signs, but > =09this new token is not the catenation operator. >=20 > This description certainly says that ## is a token, but > it is not the operator.=20 >=20 > Well, for the above description, should we read like > the following sentence? > =09...this new token is the operator as > =09preprocessing-token, but does not function as the > =09catenation operator. >=20 > Even if so, this situation violates the Constraints of > subclause 6.1.5 "Operator"(page 45 in draft 9) unless > "##" in line (A) is considered as an operator: > =09The operators # and ## shall occur in macro-defining > =09preprocessing directives only. >=20 > If we think a case that "##" is not a single > preprocessing-token, then a behavior of this example must > be undefined because of a paragraph 3 of subclause 6.8.3.3 > "the ## operator" (page 130 in draft 9): > =09If the result is not a valid preprocessing token, > =09the behavior is undefined. >=20 > Anyway, whichever we choose, that is, the violation of > the constraints or the undefined behavior, this example > is not suitable for the example of the standard C. >=20 > WG14: The current WD has new preprocessor token wording, that=20 > the Committee believes make the WD clearer in the area. =20 > The example is correct. There are NO improvement about this problem in the current=20 CD (SC22 N2620.) =20 Please refer to: "6.1.5 Operators", page 56, line 2-3 in paragraph 2: > The operators # and ## (also spelled %: and %:%:, respectively) > shall ocure in macro defining preprocessing directives only. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "6.8.3.3 The ## operator", page 163, line 8-9 in paragraph 3: > If the result is not a valid preprocessing token, > the behavior is undefined. These specifications still inconsistent with the description of the example. Japan requests again here: Please reconsder carefully the above issue.=20 3.4 Old reference to ISO/IEC 646 > 2. Editorial Comments > 1) The reference ISO/IEC 646:1983 must be ISO/IEC 646:1991. >=20 > Paragraph 1 of clause 2 (page 2 in draft 9): >=20 > The normative reference for ISO 7-bit codes character set is=20 > defined as ISO 646:1983. That is old. It must be the > latest one ISO/IEC 646:1991. >=20 > WG14: The WD will be corrected. The clause "2 Normative references" of the current CD(SC22 N2620) still referes to ISO/IEC 646:1983. The Annex A "Bibliography" also refers ISO/IEC 646:1983. Japan requests again here: Please correct them. 3.5 Locale-specific behavior > 2. Editorial Comments > 2) Locale-specific behavior >=20 > Paragraph 4 of Clause 4 (page 6 in draft 9): >=20 > The description "an implementation shall be accompanied by a > document that defines all implementation-defined > characteristics and all extensions." should also mention > "the locale-specific behavior" which is defined in the > subclause 3.13. >=20 > WG14: The WD will be corrected. There is no correction in the current CD (SC22 N2620). Please correct it. 3.6 Terminology of a null character > 2. Editorial Comments > 4) Terminology of a null character >=20 > A many variety of the representation of "null character" > is used in the draft 9. > For example,=20 > - A byte with all bits zero, subclause 5.2.1.2 (page 17) > - '\0', subclause 6.1.3.4 (page 43) > - code of value zero, subclause 6.1.4 (page 44) > - \0 escape sequence, footnote 33 (page 44) > - zero-valued code, subclause 6.5.7 (page 104) > - code value zero, subclause 7.1.1 (page 139) > - code with value zero, subclause 7.13.8.1 (page 277) > - terminating zero code, subclause 7.13.8.1 (page 278)=20 >=20 > So, they should be represented by using a same term. >=20 > WG14: The Committee discussed this issue, and reached the consensus > that a more detailed proposal would be needed to make such a=20 > major change. In the current CD (SC22 N 2620): 1) Subclause "6.5.8 Initialization" Page 133, line 3 in paragraph 18: "(including the terminating zero-valued code...)" should be changed to "(including the terminating null wide character (defined in 7.1.1)...)" 2) Subclause "7.14.8.1 Multibyte string functions" Returns Page 343, line 3 in paragraph 4: "terminating zero code" should be changed to "terminating null character (defined in 5.2.1)" 3.7 Placemaker > 2. Editorial Comments > 5) Placemaker should be included in preprocessing token. >=20 > Paragraph 1 (syntax) of Subclause 6.1 (page 26 in draft 9): >=20 > Placemaker defined in 6.8.3.2 is not included in > the syntax of preprocessing token. It should be included. > =20 > WG14: The "placemarker" preprocessing tokens are conceptually=20 > introduced during translation phase 4 and are conceptually=20 > removed before the end of phase 4; their only function is=20 > to ensure that empty macro arguments are distinct entities=20 > during macro replacement, rather than vanishing too soon. > Because "placemarker" preprocessing tokens cannot exist=20 > in the program source file, it would be inappropriate and=20 > confusing to show them in the formal grammar. Japan requests to add the WG14's above explanation as a footnote of placemarker. 3.8 A double argument for the conversion specifier > 2. Editorial Comments > 14) A double argument for the conversion specifier >=20 > Subclause 7.12.6.1 (page 232 - 233 in draft 9) and > subclause 7.18.2.1 (page 308 - 309 in draft 9): >=20 > In the description about the conversion specifier f, F, e, > E and G of the function f[w]printf,=20 > "a double argument representing a floating-point number > is..." > should be changed to=20 > "a double argument representing a normalized > floating-point number is..." ^^^^^^^^^^ > in order to clarify the range and the definition of the > double argument. >=20 > WG14: The Committee discussed this comment, and came to the=20 > consensus that this is not an editoral issue, some floating > point arithmetics support denormal numbers and infinities. > There will need to be a detailed proposal to support this=20 > change. The original intention of Japanese comment is to point out that the current description: "A double argumant representing a floating number is converted to ...[-]ddd.ddd... A double argument representing an infinity is converted to ...[-]inf or [-]infinity A double argument representing a NaN is convered to ... [-]nan or [-]nan(n-char-sequence)..." is not appropriate as a strict language standard specification because "a floating-pount number" (defined in "5.2.4.2.2 Characteristics of floating types "),=20 as WG14 mentions above, may include an infinity and a Nan so that the current description can be reasd as an infinty can be converted to [-]ddd.ddd or [-]inf and also NaN can be converted to [-]ddd.ddd or [-]Nan. Therefore, Japan re-proposes to change the above description to:=20 "A double argument representing an infinity is converted to ...[-]inf or [-]infinity... A double argument representing a NaN is converted to ... [-]nan or [-]nan(n-char-sequence)..." A double argumant representing a floating number except an infinity and a NaN is converted to ...[-]ddd.ddd..." This change should be applied to the description about the conversion specifier f, F, e, E and G of the function f[w]printf(). _______________ end of Japan comments; beginning of UK comments _____ TITLE: UK Comments for ISO/IEC CD 9899 (SC22N2620) - Information Technology Programming Languages = - C The United Kingdom Votes NO with the following comments Consideration should be given to the following: (1) Change "complex" to be a true keyword. (2) Remove the keyword "imaginary".=20 (3) Change the semantics of the keyword "restrict" to provide better facilities for optimization. In brief, replace the present "simple lock" semantics with "write once or read multiple" semantics.=20 (4) Remove the "long long" type, and reinstate the concept that "long" is the longest integer type.=20 (5) Adjust the wording concerning multiple representations of the same value for both integer and floating types where these are distinguishable, and to require constants to generate consistent representations.=20 (6) The changes introduced in the floating-point model, in particular with respect to exception handling, should be reconsidered In addition, to the above points the UK is submitting the following comments for consideration by WG14 These describe other issues that should be addressed in the CD, while no one individual comment is critical, the total number form a significant issue for the UK vote.=20 Public Comment Number PC-UK0001=20 Category: Editorial change/non-normative contribution Committee Draft subsection: various Title: Errors in applying working papers to CD1 Detailed description: This document lists the errors that have been made applying my approved papers in CD1. They are listed in this Public Comment for the record. N672 has not been applied. The change to translation phase 2 in N673 has been made, but the footnote has been lost. 7.1.8p3 should read "... returns.", not "... return"; see N675 DR147 for details. The same correction is needed in annex C. Footnote 30 should read "... and is not compatible with either.", not "and it not compatible with either.". The change was introduced in N739 item 6a. 6.5.2p4 should read "... the specifier /int/ ...". The change was introduced in N739 item 10. 7.16.3.6p6 should read "%p", not "%P" (this was introduced in N674 part G). It is also inconsistent in its use of fonts - compare %B and %p. 7.11p3 has been misedited; it reads: ... which expand to positive integer constant expressions with type /int/ and distinct values that have type compatible ... which expand to positive integer constant expressions with distinct values that are the signal numbers ... and should read: ... which expand to constant expressions with distinct values that have type compatible ... which expand to positive integer constant expressions with type /int/ and distinct values that are the signal =20 numbers ... The change was introduced in N773 item 9B. 6.3.15p4 to p6 have not been changed as required by N774 item 1. 6.5.2.3p4 should read "The type is incomplete[94]", not "The type is complete[94]". The change was introduced in N774 item 5. Footnote 227 is missing the last line: (char *) p < (char *) base + nmemb * size The change was introduced in N783 item 13. The changes relating to _exit() in N789 were omitted (at the discretion of the editorial committee). These will be resubmitted as a separate Public Comment. 7.16.1p1 should read "... and declares five types ...", not "... and declares four types ...". The change was introduced in N793. The comment within the pseudo-code in 7.16.2.6p3 is missing the last line, which should read: // if the offset cannot be determined. The change was introduced in N793, though this also seems to be missing that line. Public Comment Number PC-UK0002=20 Category: Other: correction restoring original intent Committee Draft subsection: 6.5.2.1 Title: Padding in unions - wording adjustment Detailed description: 6.5.2.1p14 no longer makes sense. The words: were the structure or union to be an element of an array should be deleted. Public Comment Number PC-UK0003 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 6.3.2.2 Title: Adjustment to permitted incompatible argument types Detailed description: The excepted cases in 6.3.2.2p5 were meant to be slightly less restrictive than the wording given. The second bullet point should read: - both types are pointers to qualified or unqualified versions of /void/ or of character types. In addition, paragraph 6 should be part of paragraph 5; it is easy to misparse the present arrangement. It could also be made easier by changing the first words of the paragraph to: Furthermore, if the function ... =20 Public Comment Number PC-UK0004 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.3.7 Title: Shift operators - wording tidy up Detailed description: Now that the term "width" is available, 6.3.7p3 could be reworded; the last sentence should read: If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined. =20 Public Comment Number PC-UK0005 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 3.18, 6.8.5 Title: Make #error have the desired effect Detailed description: Consider the program: #error foo int main(void) { return 0; } This does not violate any of 3.18p3: The implementation must successfully translate a given program unless a syntax error is detected, a constraint is violated, or it can determine that every possible execution of that program would result in undefined behavior but clearly ought to. A reasonable way to fix this is to add to the end of 3.18p3: The implementation must not successfully translate a program that contains a #error preprocessing directive that is not part of a group that is skipped by conditional inclusion. =20 Public Comment Number PC-UK0006 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.1.4 Title: Clarification concerning overlapping string literals Detailed description: The first sentence of 6.1.4p6 does not fall into any of the three types of behavior. Better wording would be: It is unspecified whether these arrays overlap or not, provided that their characters have the appropriate values. Public Comment Number PC-UK0007 Comment 1.=20 Category: Other: outstanding problem Committee Draft subsection: 6.5.3.1 Title: Problem with restrict and string literals Detailed description: Consider the function call: fopen ("bar", "r"); Because both parameters of open() have restrict-qualified type, it is not permitted for the two strings to share storage. However, an implementation which shares string literals might do so, possibly without the programmer realizing that the situation happened (for example, the first parameter might be a macro defined in a makefile). The correct solution is to exempt string literals from the rules concerning restrict, but I am not familiar enough with the wording to try. Public Comment Number PC-UK0008 Comment 1.=20 Category: Other: moving normative text to a normative section Committee Draft subsection: Introduction, 1 Title: The definition of normative text should be normative. Detailed description: The Introduction contains the text: The introduction, the examples, the footnotes, the references, and the annexes are not part of this International Standard. However, this text is not normative, and so it is not clear what text is and is not normative. It is alss wrong. Delete the sentence from the Introduction. Add a new paragraph 3 to clause 1: Annexes F and I are normative. The introduction, the examples, the footnotes, the references, and the remaining annexes are not part of this International Standard. Public Comment Number PC-UK0009 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 7.16.3.6 Title: Lacuna in strftime() %z Detailed description: The description of %z does not say what to do if no time zone can be determined. After the parenthesized clause, insert the words: or no characters if no time zone is determinable. Public Comment Number PC-UK0010 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.16.1 Title: _NO_LEAP_SECONDS should require a sensible value Detailed description: After the symbol _NO_LEAP_SECONDS in 7.16.1p2, add the comment: _NO_LEAP_SECONDS // must be outside the range [-3600, +3600] Public Comment Number PC-UK0011 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.16.1 Title: require a type for _NO_LEAP_SECONDS and _LOCALTIME. Detailed description: At the end of 7.16.1p2 add the words: which are integral constant expressions with type /int/. Public Comment Number PC-UK0012 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 7.16.1 Title: Fix definition of "broken-down time". Detailed description: The term "broken-down time" is clearly intended to refer to both the types "struct tm" and "struct tmx". Change the last part of 7.16.1p3 from: ... representing times; /struct tm/ which holds the component of a calendar time, called the /broken-down time/; and /struct tmx/ which is an extended version of /struct tm/. to: ... representing times; and /struct tm/ and /struct tmx/ which hold the components of a calendar time, called the /broken-down time/, in two slightly different ways. Public Comment Number PC-UK0013 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 6.1.2.5, 6.5.2.1 Title: Cleanup of flexible array structure members. Detailed description: The concept of flexible array structure members, otherwise known as the "struct hack", has a number of minor problems that need fixing. Furthermore, there are some nasty implications when such a structure is used as a component of an aggregate type, this is forbidden. 6.1.2.5p17, bullet point 2, should read: A /structure type/ describes a sequentially allocated nonempty set of member objects (and, in certain circumstances, an incomplete array), each of which has an optionally specified name and possibly distinct type. 6.5.2.1p2, first sentence, should read: ... except that the last member of a structure with more than one named member may have incomplete array type; such a structure (and any union containing, possibly recursively, a member whose type is such a structure) shall not be the type of a member of a structure or of the eleme= nt of an array. 6.5.2.1p15 should be replaced by: As a special case, the last member of a structure with more than one named member may have an incomplete array type. This is called a /flexible array member/, and the size of the structure shall be equal to the offset o= f the last member of an otherwise identical structure that replaces the fle= xible array member with an array of unspecified length [*]. When an lvalue whose type is a structure with a flexible array member is used to access an object, it behaves as if that member were replaced with the longest array, with the same element type, that would not make the structure larger than the object being accessed; the offset of the array shall remain that of the flexible array member, even if this would differ from that of the replacement array. If this array would have no elements, then it behaves as if it had one element, but the behavior is undefined if any attempt is made to access that element or to generate a pointer one past that element. [*] The length is unspecified to allow for the fact that some implementations may give array members different alignments according to their length. Change the start of paragraph 16 to: Assuming that all arrays have the same alignment within structures, then after the declarations: struct s { int n; double d[]; }; struct ss { int n; double d[42]; }; the three expressions: In paragraph 17, change: /s1/ and /s2/ behave as if they had been declared as: to: the objects pointed to by /s1/ and /s2/ behave as if the latter two identifiers had been declared as: Public Comment Number PC-UK0014 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 6.5.8 Title: problems with initializing unsigned char arrays. Detailed description: Consider the following declaration: unsigned char s [] =3D "\x80\xff"; The first element of the string literal has the value: (char) 128 and the second element has the value: (char) 255 If the type char is signed and CHAR_MAX is less than 128, these two expressions are implementation-defined. In particular, on a ones-complement implementation likely values are -127 and -0 respectively. When these are converted back to unsigned char during the initialization, then (if UCHAR_MAX is 255) they will be converted to 129 and 0 respectively. This is *not* intuitive. Append to 6.5.8p17: The value of each element is determined by converting the corresponding numerical representation of the mapped character, or the octal or hexadecimal escape sequence, directly to the array element type, not via the type char. Append to example 7 in 6.5.8p24: The declaration: unsigned char c [] =3D "\xFF"; is identical to: unsigned char c [2] =3D { 0xFF, 0 }; and not to: unsigned char c [2] =3D { (unsigned char)(char) 0xFF, 0 }; (the latter could be different if /CHAR_MAX/ is less than 255 and the implementation-defined value of the expression /(char) 0xFF/ is not equal to /254-UCHAR_MAX/). Public Comment Number PC-UK0015 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 5.2.4.2.1 Title: ensure int can hold all characters and EOF Detailed description: To eliminate a pathological case, append to 5.2.4.2.1p2: On a hosted implementation, INT_MAX shall be not less than UCHAR_MAX. Public Comment Number PC-UK0016 Comment 1.=20 Category: Normative change to intent of existing feature Committee Draft subsection: 6.1.1 Title: eliminate conditional keywords Detailed description: 6.1.1 makes the keywords "complex" and "imaginary" only be "reserved" if the header is included. This is a problem for two different reasons. Firstly, cautious programmers will assume that the keywords might be needed at some later date, for example by a system header that they have no control over. Therefore they will have to play safe and not use them. The less cautious may use them, and then be burnt later when such a change outside their control happens. Both cases bring the Standard into disrepute. Seeing that the decision has already been made to introduce new keywords, there is little benefit in this approach unless it is going to be more radical (for example, making complex types be unavailable on freestanding implementations). And, even so, there are better approaches. Secondly, the term "reserved" is being misused. This term (see 7.1.3) means that an identifier may not be redeclared. Keywords are not identifiers, and thus reservation is nonsense. In any case, the syntax does not allow a keyword to be used as if it were an identifier. Three alternatives are given here; my preference is for the third. Alternative 1: delete 6.1.1 paragraph 2. Alternative 2: if it is still viewed as desirable to make the names "complex" and "imaginary" available to programmers not using , then: * Change the keywords in 6.1.1 to __complex and __imaginary. * Add to 7.8 a new paragraph 4: The macro /complex/ is defined to be /__complex/. If and only if the macro /_Imaginary_I/ is defined, then the macro /imaginary/ is defined to be /__imaginary/. Notwithstanding the provisions of subclause 7.1.3, it is permitted to undefine the macros /complex/ and /imaginary/. Alternative 3: since complex types are basic to the language while imaginary types are an extension: * Change the keyword imaginary in 6.1.1 to __imaginary.=20 * Add to 7.8 a new paragraph 4: If and only if the macro /_Imaginary_I/ is defined, then the macro /imaginary/ is defined to be /__imaginary/. Notwithstanding the provisions of subclause 7.1.3, it is permitted to undefine the macro /imaginary/. Public Comment Number PC-UK0017 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 6.3.9 Title: fix pointer comparison Detailed description: DR 172 addressed a number of defects in the rules for pointer comparison, and the DR authors suggested new wording to fix this. This issue was also raised in WG14 papers N720 and N783. Following other changes in the Standard, this wording is no longer completely acceptable. Instead, replace 6.3.9 paragraphs 3 to 5 with the following text. The =3D=3D (equal to) and !=3D (not equal to) operators are analogous t= o the relational operators except for their lower precedence.[78] They yield 1 if the specified relation is true and 0 if it is false. The result has type /int/. For any pair of operands, one operator shall be true and the other false. If both of the operands have arithmetic type, the usual arithmetic conversions are performed. [[Insert the existing paragraph 5 here.]] Otherwise the operands are pointers; if one is a pointer to an object or incomplete type and the other has type pointer to a qualified or=20 unqualified version of /void/, the former is converted to the type of the latter. Two pointers shall compare equal if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning), the same element of an array object, or the same function, if both are pointers to one past the end of the same array object, or if one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to be immediately after it in the address space.[79] Otherwise they shall compare unequal. Prepend to footnote 79: Two objects may be adjacent in memory because they are adjacent elements of some larger array object, because they are adjacent members of a structure with no padding between them, or because they are unrelated and the implementation chooses to place them adjacent in memory. Public Comment Number PC-UK0018 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.1.2.7, 6.3.1.1 Title: merge predefined identifiers into one place Detailed description: The concept of predefined identifiers is found in two separate places: 6.1.2.7 and 6.3.1.1. The latter location is, I believe, historical cruft from when __func__ was treated as a special entity. It would read better to merge the two sections into one, and 6.1.2.7 is a better location. Delete subclause 6.3.1.1. Replace subclause 6.1.2.7 by the following: 6.1.2.7 Predefined identifiers The identifiers described in the following subclauses shall be implicitly defined by the implementation. 6.1.2.7.1 The identifier __func__ [[Insert the body of the present 6.3.1.1 here.]] Public Comment Number PC-UK0019 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 5.1.1.2, 6.3.1.1 Title: handling of characters not in the execution character set Detailed description: Consider the code extract: char *s =3D "\u30CE"; During translation phase 5 the universal character name is converted to a multibyte character. However, it is not stated what happens if the implementation does not have a representation for Katakana (30CE is within the Katakana range of annex I). Therefore it is implicitly undefined. Now consider the following translation unit: #include void fff (void); void \u30CE (void); int main (void) { fff (); \u30CE (); return 0; } void fff (void) { printf ("This is %s\n", __func__); } void \u30CE (void) { printf ("Hello world!\n"); } This is clearly strictly conforming (unless I've made an error :-). Now consider the trivial change: #include void fff (void); void \u30CE (void); int main (void) { fff (); \u30CE (); return 0; } void fff (void) { printf ("Hello world!\n"); } void \u30CE (void) { printf ("This is %s\n", __func__); } This is now undefined on any implementation that cannot represent the Katakana character set ! I have trouble believing that this was intended, and I certainly feel that, if it is retained, it should be flagged in the text of the Standard. Public Comment Number PC-UK0020 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 4 Title: Adjust wording of footnote 2 Detailed description: Footnote 2 is not particularly clear. Better wording would be: A strictly conforming program can use conditional features, such as those in annex F, provided that the use is guarded by an #ifdef directive with the appropriate macro. For example: [[followed by the existing example]] Public Comment Number PC-UK0021 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 4 Title: Further requirements on the conformance documentation Detailed description: There are many things that the Standard requires to be documented, but not all of them are listed in 4p4. Change it to: An implementation shall be accompanied by a document that describes all features that this International Standard requires to be described by the implementation, including all implementation-defined characteristics and all extensions. Public Comment Number PC-UK0022 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 5.1.1.2 Title: Translation phase 6 is inconsistent Detailed description: Change TP 6 in 5.1.1.2p1 to read: Adjacent character string literal tokens and wide string literal tokens are concatenated. Public Comment Number PC-UK0023 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 6.5.2.1, 6.5.6 Title: Removing implicit int, further lacunae Detailed description: The requirement for a type specifier has been omitted from 6.5.2.1 and 6.5.6. In each case, add a constraint: At least one type specified shall be given in each specifier-qualifier-list. Public Comment Number PC-UK0024 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.1.2.5 Title: Replace footnote 25 Detailed description: Footnote 25 is unclear in context. A better description of the situation is in footnote 29. Replace the text of FN25 with that of FN29, and change all references to the latter to be references to the former. Public Comment Number PC-UK0025 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.1.3.2 Title: clarify the explanation of the types of an integer constant Detailed description: 6.1.3.2p5 is rather difficult to read. Better would be to replace it with a table, like this: The type of an integer constant is the first one marked with an X in the corresponding column of the table in which its value can be represented: Suffix: - - U L L LU LL LL LLU Base: D O/H - D O/H - D O/H - signed int X X unsigned int X X signed long X X X X unsigned long X X X X signed long long X X X X X X unsigned long long X X X X X X /signed extended/ X X X /unsigned extended/ X X X /any extended/ X X X Notes: suffixes may be in either case, and where there are two suffixes, in either order. D =3D decimal O/H =3D octal or hexadecimal If an integer constant cannot be represented by any standard type in its list, it may be represented by an extended integer type if there is one that can represent that value. The type must be signed or unsigned if so indicated. Alternatively, the ad hoc nature of the present description could be replaced by one more structured: The type of an integer constant is the first one in the following list in which its value can be represented: /signed int/, /unsigned int/, /signed long int/, /unsigned long int/, /signed long long int/, /unsigned long long int/ and subject to the following restrictions: - if suffixed by /u/ or /U/, then omit the signed types - if decimal and not suffixed by /u/ or /U/, then omit the unsigned types - if suffixed by /l/ or /L/, then omit the first pair - if suffixed by /ll/ or /LL/, then omit the first two pairs If an integer constant cannot be represented by any of the types permitted by the above, it may be represented by an extended integer type if there is one that can represent that value and which has the same signedness as at least one of the permitted standard types. Public Comment Number PC-UK0026 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.1.4 Title: improve the example of character string literals Detailed description: Append to 6.1.4p7, the example: When this is used to initialize a static array, the array has three members that are initialized to /18/, the value of /'3'/, and /0/ respectively. Public Comment Number PC-UK0027 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 5.1.1.2, 5.2.1, 5.2.1.2, 6.1.2, 6.1.2.5, 6.8 Title: inconsistencies in use of "basic" and "extended" character sets and in their relationship to UCNs Detailed description: The Standard uses the terms "basic character set" and "extended character set" at various places. However, the exact meaning of these two is not clear, and this leads to confusion. Consider the UTF-8 encoding (codes from 0 to 127 are single byte, codes from 128 to 255 form part of multibyte characters with length from 2 to 5 bytes). There are five possible execution character sets: [1] The 95 characters required by 5.2.1p3, plus the null character. [2] The 128 single byte characters. [3] The 2**31 multibyte characters. [4] Set [3] minus set [1]. [5] Set [3] minus set [2]. (and corresponding source sets). It is unclear whether the "basic character set" means [1] or [2]. The use of the wording "at least the following members" in 5.2.1p3 implies that the basic set can be larger than [1]. On the other hand, if the term is taken to represent [2], then 5.1.1.2p2 would forbid using \u0040 to represent the @ sign, something which I do not believe was intended, since it means that the \u form would be forbidden for *all* characters in the implementation-defined "basic" set. Consideration of this and related matters has led me to believe that it is most useful to have terms for [1] and for [4], while on the other hand there is little or no need to refer to [2], [3], and [5]. Therefore "basic character set" should represent [1] and "extended character set" should represent [4]. To do this requires a number of changes. Replace 5.2.1p1, second sentence, by: Each set is further divided into a /basic/ set, whose contents are given by this subclause, and an /extended/ set, consisting of zero or more locale-specific members (which are not members of the basic set). In 5.2.1p3, delete "at least" in the first sentence, and in the fourth sentence change "In the execution character set" to "In the basic execution character set". Delete the last sentence of 5.2.1p3 ("If any other characters ... the behavior is undefined"). It is useless for several reasons: - If translation phase 1 is taken literally, all members of the extended character set are replaced by UCNs, which consist of members of the basic character set (this point is further addressed below). While some are converted back in translation phase 5, all such characters are included in = the exemptions. - It does not allow for UCNs in identifiers. - If such a character was encountered, the preprocessing token it is in is either not converted to a token (in which case the sentence does not apply) or *is* converted; in the latter case, the constraint of 6.1p2 is violated and this sentence has no effect. Delete 5.1.1.2p2, and replace it by a constraint at the end of 5.2.1 (forming a new paragraph 6): Constraint A universal-character-name shall not specify (in either form) a character short identifier less than 00A0 other than the following: 0024 0040 0060 This is a more consistent position for the restriction, and it has the useful side effect of making it clear what the UCNs of the basic character set *are*. Replace 5.2.1.2p1, first bullet, by: - The basic character set shall be present and shall be encoded using single-byte characters. There is no longer a need to check for the shift states of comments, string literals, and so on, because during translation phase 1 these will have been converted to a stateless representation using UCNs. Therefore replace 5.2.1.2p2 by: If a source file does not consist of a valid sequence of multibyte characters, the behavior is undefined. In 6.1.2.5p2, replace "required source character set enumerated in 5.1.2" with "basic execution character set" (note that the execution set is more sensible in this context than the source set). The second sentence of 6.1.2p2 restricts UCNs in identifiers to those listed in annex H. If some other UCN appears, it is unclear whether the behavior is undefined, or whether the UCN is not part of the identifier. This is further complicated by the example in footnote 122. If the text appeared in a source file, by translation phase 4 it would be processed as: #define THIS\u0024AND\u0024THAT(a,b) ((a)+(b)) and so the replacement list *does* begin with a character required by subclause 5.2.1, and thus this is unambiguously a definition of the object-like macro THIS. However, this completely wrecks the whole point of 6.8p4 and FN122 (added in TC1). Replace the second sentence of 6.1.2p2 with: Only universal-character-names corresponding to the characters listed in annex I are nondigits.[20] and append to footnote 20: Since 00A0 is not listed in annex I, but 00C0 is, the sequence of characters a\u00C0b\u00A0 consists of two preprocessing tokens; the first is an identifier made up of three nondigits. (note also the correction to the annex cited). Replace 6.8p4 by: In the definition of an object-like macro, either the replacement list shall be separated from the identifier by white space, or it shall begin with one of the 26 graphic characters in the basic character set other than ( _ or \ (and thus shall not begin with a =20 universal-character-name).[122] Public Comment Number PC-UK0028 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 5.2.4.1 Title: clarify translation limit for identifiers using UCNs. Detailed description: In 5.2.4.1, change the relevant translation limits to: - 63 significant initial characters in an internal identifier or a macro name (a universal-character-name shall count as one) - 31 significant initial characters in an external identifier (a univeral-character-name shall count as 4 if less than 0000FFFF, and 8 otherwise) or some other wording that reflects the Committee's intent if different. Public Comment Number PC-UK0029 Comment 1.=20 Category: [one of the following] Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 5.2.4.2.2 Title: clarify rounding to nearest Detailed description: In 5.2.4.2.2p5, change the third case: 1 to nearest to: 1 to nearest (if the value to be rounded is exactly between two representable values, it is unspecified which is chosen) Public Comment Number PC-UK0030 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 5.1.1.2 Title: Require UCNs to appear in translation phase 1 Detailed description: Currently, a source file can contain: \u12\ 34 and it is unclear whether or not this is a universal character name. Add to the end of 5.1.1.2 translation phase 2: If a character sequence that matches the syntax of a universal-character-name is produced by such splicing, the behavior is undefined. =20 It is also unclear whether: ??/u1234 is a universal character name or not. I think the current wording allows it, but a footnote would be a good idea. Public Comment Number PC-UK0031 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.3.1.9, 7.18.2.1.9 Title: make ispunct() true for basic punctuation characters Detailed description: There appears to be no character for which it is required that ispunct() is true. This is surprising, to say the least, as one would expect that it is true for characters like '.' and '('. Replace 7.3.1.9p2 by EITHER: The /ispunct/ function tests for any printing character for which neither /isspace/ nor /isalnum/ is true. OR: The /ispunct/ function tests for any character that is one of the 29 graphic characters in the basic execution character set or is one of a locale-specific set of printing characters for which neither =20 /isspace/ nor /isalnum/ is true. In the "C" locale it returns true only for the characters in the basic execution character set. [These two are not equivalent outside the "C" locale.] Public Comment Number PC-UK0032 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 6.1.2.1 Title: tidy-up specification of overlapping scopes Detailed description: The use of "non-overlapping" in 6.1.2.1p implies that the "scope" of an identifier excludes any block where the identifier is redeclared. This is inconsistent with the description of inner and outer scopes in paragraph 3; the latter is probably preferable. Change the word "non-overlapping" in paragraph 1 to "different". Public Comment Number PC-UK0033 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.3.2.2 Title: Fix wording relating to "number of arguments" Detailed description: 6.3.2.2p2 states "the number of arguments shall agree with the number of parameters". This does not clearly take account of varargs functions. Change the wording to: the number of arguments shall equal or, if the prototype ends with an ellipsis (, ...), shall be no less than, the number of parameters (excluding any ellipsis). Public Comment Number PC-UK0034 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.3.2.3 Title: Adjust wording concerning qualifiers on structure members Detailed description: 6.3.2.3p3 reads, in part: If the first expression has qualified type, the result has the so-qualified version of the type of the designated member. This should read: The result has all the qualifiers of the first expression and those of the designated member. Also add an example: In: struct s { int i; const int ci; }; struct s s; const struct s cs; volatile struct s vs; the various members have the types: s.i int s.ci const int cs.i const int cs.ci const int vs.i volatile int vs.ci volatile const int Public Comment Number PC-UK0035 Comment 1.=20 Category: Normative change to intent of existing feature Committee Draft subsection: 6.3.2.4, 6.3.3.1 Title: Allow increment/decrement of complex objects. Detailed description: All the operators that can be applied to a real floating object can also be applied to complex ones, with the sole exception of ++ and --. There is no obvious reason for this exception (particularly since the ! operator can be applied). In 6.3.2.4p1 and 6.3.3.1p1, change "real" to "arithmetic". Public Comment Number PC-UK0036 Comment 1.=20 Category: Normative change where the intent is unclear Committee Draft subsection: 6.3.16 Title: Define the result of the assignment operator Detailed description: 6.3.16p3 states: An assignment expression has the value of the left operand after the assignment, but is not an lvalue. It is not clear what this means when the left operand is a volatile object that changes through external causes - it could mean the value stored, or it could mean the result of reading the object. Replace these words with the unambiguous: The value of the assignment expression is the value stored in the left operand, but is not an lvalue. Public Comment Number PC-UK0037 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 6.4 Title: Constant expression cannot contain the size of a VLA Detailed description: 6.4 does not require a constraint for "sizeof(v)" where v has variable length array type. FN83 also fails to notice this case. Append to 6.4p3: Any /sizeof/ operator shall have an operand whose size is defined to be constant. Move the reference to FN83 to the new end of the paragraph, and within the footnote change: not evaluated to: not evaluated when no component of the operand has variable length array type In 6.4p6 remove the words "sizeof expressions ... name of such a type". Public Comment Number PC-UK0038 Comment 1.=20 Category: Feature that should be removed Committee Draft subsection: 6.1.8 Title: UCNs should not be permitted in preprocessing numbers Detailed description: The syntax in 6.1.8p1 uses "nondigit", which used to represent the 52 letters plus underscore but now also includes the UCNs in Annex I. I believe this is a mistake, and the syntax should be adjusted =20 accordingly. Public Comment Number PC-UK0039 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 6.1.3.1 Title: Allow 'i' suffix for floating constants Detailed description: It should be possible to write an imaginary floating point constant rather than having to multiply by the macro /I/. Furthermore, this macro is not available in a free-standing implementation. The obvious way to do this is to allow the suffix 'i' or 'I'. To do so: In 6.1.3.1p1: - Remove "floating-suffix/opt" from the various alternatives to "decimal-floating-constant" and "hexadecimal-floating-constant". =20 - Append "floating-suffices/opt" to each alternative for "floating-constant". - Add: floating-suffices: floating-suffix imaginary-suffix imaginary-suffix floating-suffix imaginary-suffix: one of i I Append to 6.1.3.1p4: If the constant has the suffix /i/ or /I/, then its type and value are that resulting when the constant without that suffix is multiplied by the value of the macro /I/ defined in the header and add a forward reference to 7.8. Public Comment Number PC-UK0040 Comment 1.=20 Category: Normative change to intent of existing feature Committee Draft subsection: 6.5.2.1 Title: Bitfields of non-standard types should require a diagnostic. Detailed description: If a bitfield is declared with a type other than plain, signed, or unsigned int, the behavior is undefined. Since this can easily be determined at compile time, it should generate a diagnostic. An exception i= s required for the type underlying /bool/, and perhaps for any type that can have valid bitfields. Delete the first sentence of 6.5.2.1p8. Add to the end of 6.5.2.1p3: A bit-field shall have a type that is a qualified or unqualified version of /signed int/ or /unsigned int/, or of the type /bool/ defined in the header . or: A bit-field shall have a type that is a qualified or unqualified version of /signed int/ or /unsigned int/, of the type /bool/ defined in the header , or of some other implementation-defined integer type. Public Comment Number PC-UK0041 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 6.5.2.2, 6.5.2.3 Title: An example uses an incomplete type in the wrong context Detailed description: 6.5.2.3 example 3 uses the line: enum f { c =3D sizeof (enum f) }; but 6.5.2.2p5 indicates that the type is not complete at the point it is used in the constant expression, and so a constraint is violated. The example must be reworded or deleted. Public Comment Number PC-UK0042 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.5.4 Title: Clarify some aspects of inline Detailed description: In 6.5.4p6, add a footnote referenced at the end of the paragraph: [*] The call need not be due to the direct appearance of the name of the function at the point of calling; it may be through some kind of indirection. In 6.5.4p8, after: because /fahr/ is also declared with /extern/ add: (even though that declaration is not visible at the definition of /fahr/) Public Comment Number PC-UK0044 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 6.5.7 Title: Removal of implicit int - further lacunae Detailed description: In 6.5.7p3, the last sentence: If the identifier is redeclared in an inner scope or is declared as a member of a structure or union in the same or an inner scope, the type specifiers shall not be omitted in the inner declaration. are no longer needed, as the type specifiers cannot be omitted. Public Comment Number PC-UK0046 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.5.7 Title: Correct ranges of bitfields in an example Detailed description: In 6.5.7 example 3, change the specified ranges: - from "at least the range [-15, +15]" to "either the range [-15, +15] or the range [-16, 15]=20 - from "values in the range [0, 31] or values in at least the range [-15, +15]" to "values in one of the ranges [0, 31], [-15, +15], or [-16, +15]" Public Comment Number PC-UK0047 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 6.8 Title: Handling of unknown preprocessing directives Detailed description: In the preprocessing phase (translation phase 4), consider the line: # unknown command It is unclear whether or not this requires a diagnostic. Presumably the # punctuator will remain until translation phase 7 where it cannot fit in the syntax, but even if so, this is less than clear. However, this is easy to fix. In the syntax in 6.8p1, change group-part to: group-part: non-directive new-line if-section control-line and add: non-directive: pp-tokens/opt Then add a constraints clause: Constraint The first preprocessing-token (if any) in a non-directive shall not be /#/. Finally, delete 6.8.3p8, because this can no longer occur. Public Comment Number PC-UK0048 Comment 1.=20 ? Category: Other: unresolved issue Committee Draft subsection: 6.1.7, 6.8.2 Title: Problems with UCNs in header file names Detailed description: Consider the line: #include "a$b.h" This will be changed, in translation phase 1, to: #include "a\u0024b.h" Both of these involve undefined behavior, but equally both are valid file names on at least one common operating system. It is likely that implementations that implement UCNs in a natural manner are going to have problems deciding which of the names was intended. I'm not clear what the answer is, but it needs addressing. Public Comment Number PC-UK0049 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 6.8.1 Title: Handling of UCNs in character constants in #if directives Detailed description: Consider the line: #if '\u0024' < 100 where dollar is in the single-byte execution character set. It is not completely clear from 6.8.1p3 that the UCN is converted to a single character, since this normally happens in translation phase 5. In 6.8.1p3, last two lines of page 157 (postscript version), change: ... which may involve converting escape sequences into execution character set members. Whether =2E. to: ... which may involve converting source character set members, escape sequences, and universal character names into execution character set members in the manner of translation phase 5. However, =20 whether ... Public Comment Number PC-UK0050 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 6.1.2.8.1, 6.3.2.3 Title: Effects on other members of assigning to a union member Detailed description: 6.3.2.3p5 has wording concerning the storing of values into a union member: With one exception, if the value of a member of a union object is used when the most recent store to the object was to a different member, the behavior is implementation-defined. The requirement to be implementation-defined means that an implementation must ensure that all stored values are not trap representations in the types of other members, and thus, in effect, eliminates the possibility of trap representations at all. It turns out that the wording of 6.1.2.8.1 is sufficient to explain the behavior in these circumstances, and the cited wording in 6.3.2.3 merely muddles the issue. It should be removed; the rest of the paragraph can stand alone. Public Comment Number PC-UK0051 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 7.1.7 Title: true and false are not reserved identifiers Detailed description: 7.1.7p3 defines "true" and "false" as macros, which thus a reserves them in accordance with the third bullet of 7.1.3. FN138 suggests that an implementation could use these names as enumeration constants, but they are not reserved in that context. That is: #include #undef true; complex long double true; is strictly conforming. Since the implementation in the footnote is a useful one (for the reasons given), 7.1.7 should reserve these names at file scope, either explicitly or by changing these two identifiers to be "const int" (though of course this would give them an address). Public Comment Number PC-UK0052 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 6.8.3 Title: Add a __VA_COUNT__ facility for varargs macros Detailed description: Unlike with function calls, it is trivial for an implementation to determine the number of arguments that match the ... in a varargs macro. There are a number of useful things that can be done with this (at the least, providing argument counts to varargs functions). Therefore this information should be made available to the macro expansion. In 6.8.3p5, change The identifier /__VA_ARGS__/ ... to: The identifiers /__VA_ARGS__/ and /__VA_COUNT__/ ... Append to 6.8.3.1p2: The identifier /__VA_COUNT__/ that occurs in the replacement list shall be treated as if it were a parameter; it is replaced by a single token which is the number of trailing arguments (as a decimal constant) that were merged to form the variable arguments. Public Comment Number PC-UK0053 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 7.4 Title: Require consistency if an implementation adds to Detailed description: 7.20.3 reserves all names such as int11_t and uint_least22_t. This allows implementations to define them in , but does not require these names to be handled consistently. Adding such a requirement would aid portability. This proposal does not require any types other than those already required by the header. [The following is a minimal change. If requested, I can rewrite the header = to integrate the changes better.] Append to 7.4 as a new paragraph 5: For each typedef name listed as /optional/ and which can be defined as a type existing in the implementation, it is unspecified whether or not the type is defined, but if it is provided, so shall the corresponding limit and /fprintf/ macros (as with all the types in this header, the /fscanf/ macros are optional). Append to 7.4.1.1, 7.4.1.2, and 7.4.1.3 as a new paragraph 4: Any other typedef name of these two forms is an optional type. Append to 7.4.2 as a new paragraph 3: Any optional types shall have /MAX/ and, if signed, /MIN/ macros with the appropriate name and value as if explicitly included in the following subclauses. For example, if the type /uint14_t/ is provided, then the macro UINT14_MAX shall be provided with value exactly 16383. Append to 7.4.4p1: Any optional types shall have /fprintf/ and /fscanf/ macros with the appropriate name and value as if explicitly included in the following lists. For example, if the type /uint14_t/ is provided, then the macros /PRIo14/, /PRIu14/, /PRIx14/, /PRIX14/, /SCNo14/, /SCNu14/, and /SCNx14/ should be added to the lists below. Public Comment Number PC-UK0054 Comment 1.=20 Category: Other: C++ conflict avoidance Committee Draft subsection: 6.8.8 Title: Require that __cplusplus not be defined Detailed description: Add to 6.8.8 a new paragraph 5: The implementation shall not predefine the macro /__cplusplus/, nor shall it define this macro in any header defined in clause 7. Public Comment Number PC-UK0055 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 7.8 Title: It should be explicitly possible to redefine I Detailed description: 7.8p3 should end: Not withstanding the provisions of subclause 7.1.3, it is permitted to undefine and redefine the macro I. This was clearly the intent. Public Comment Number PC-UK0056 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 7.1.6 Title: Add a symbol giving the maximum alignment Detailed description: [I eventually decided is the right place for this.] Add a new macro to : _ALIGNMENT_ALL which expands to an integer constant expression that has type /size_t/, the value of which is the least common multiple of the alignments of all object types.[*] [*] If /p/ has pointer to character type and is suitably aligned for some type /t/, then /(p + _ALIGNMENT_ALL)/ is also suitably aligned for the same type /t/, no matter what /t/ is. Possibly also add the macros: _ALIGNMENT_INTS _ALIGNMENT_FLOATS _ALIGNMENT_POINTERS which are the least common multiples of the alignments for integer types, for floating types, and for pointer types respectively. Other names could also be conceived of (_ALIGNMENT_STRUCTS, _ALIGNMENT_UNIONS, _ALIGNMENT_SCALARS, etc.). Public Comment Number PC-UK0057 Comment 1.=20 Category: Normative change to intent of existing feature Committee Draft subsection: 7.13.2, 7.13.3, 7.19.3.10, 7.19.7 Title: Better locale handling for wide oriented streams Detailed description: 7.13.2p6 associates an /mbstate_t/ object with each stream, and 7.13.3p11-13 state that this is used with the various wide-oriented functions. On the other hand, 7.19.7p3 places very strict restrictions on the use of such objects, restrictions that cannot be met through the functions provided in the Standard while allowing convenient use of wide formatted I/O. Furthermore, an /mbstate_t/ object is tied to a single locale based on the first time it is used. This means that a wide oriented stream is tied to the locale in use the first time it is read or written. This will be surprising to many users of the Standard. Therefore, at the very least these objects should be exempt from the restrictions of 7.19.7; the restrictions of 7.13 (for example, 7.13.2p5 bullet 2) are sufficient to prevent unreasonable behaviour. In addition, the locale of the object should be tied and not affected by the current locale. The most sensible way to do this is to use the locale in effect when the file is opened, but allow /fwide/ to override this. In 7.13.2p6, add after the first sentence: This object is not subject to the restrictions on direction of use and of locale that are given in subclause 7.19.7. All conversions using this object shall take place as if the /LC_CTYPE/ category setting of the c= urrent locale is the setting that was in effect when the orientation of the= stream was set with the /fwide/ function or, if this has not been used, when the stream was opened with the /fopen/ or /freopen/ function. In 7.19.3.10, add a new paragraph after paragraph 2: If the stream is successfully made wide oriented, the /LC_CTYPE/ category that is used with the /mbstate_t/ object associated with the stream shall be set to that of the current locale. In 7.19.7p3, append: These restrictions do not apply to the /mbstate_t/ objects associated w= ith streams. Public Comment Number PC-UK0058 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 7.13.4.3 Title: Unclear how many times tmpfile() can be called. Detailed description: Nowhere does the Standard state how many times tmpfile() can be called, nor does it state that several successful calls will actually access different files ! Append to 7.13.4.3p2: The file will be different from any other existing file, including any opened by a previous successful call to the /tmpfile/ function.=20 Add a new part to 7.13.4.3: Recommended practice It should be possible to open at least /TMP_MAX/ temporary files during the lifetime of the program, and no limit on the number simultaneously open other than this limit and any limit on the =20 number of open streams (FOPEN_MAX). The limit of /TMP_MAX/ could be shared with calls to /tmpnam/. Public Comment Number PC-UK0059 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 6.8 Title: Add a description of the start symbol to the preprocessing grammar Detailed description: There is (still) no clear description of the grammar that a preprocessing file needs to obey. That is, the grammar is there but its applicability is not given. Add a new paragraph to 6.8 just before paragraph 5: As discussed in 5.1.1.1, the unit of program text before preprocessing (at the start of translation phase 4) is a preprocessing file. As shown in the grammar above, this consists of a sequence of conditional inclusion blocks, other preprocessing directives, and other text. Public Comment Number PC-UK0060 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 7.2 Title: Clarify multiple insertions of Detailed description: The rules for including are partly in 7.1.2 and partly unstated. They should be stated more clearly in 7.2. Add to the end of 7.2p1: The /assert/ macro is redefined according to the current state of /NDEBUG/ each time that // is included. Public Comment Number PC-UK0061 Comment 1.=20 Category: Normative change to intent of existing feature Committee Draft subsection: 7.2.1 Title: Explicitly allow assert on non-integer arguments Detailed description: A DR response stated that assert need not correctly handle arguments which are not of type int but can be compared with zero. At the very least, this forbids arguments which are unsigned int or long, let alone other scalar types. Since it is trivial to have the macro convert any scalar to truth value integer by prefixing it with the !! operator, this restriction should be removed. In 7.2.1.1p1, change "int expression" to "scalar expression", where the word "scalar" is in italics. Add to paragraph 2, either after the first sentence or at the end: The argument of the /assert/ macro is any expression with scalar type. Public Comment Number PC-UK0062 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 7.13.3, 7.13.5.4 Title: Provide a way to make the standard streams binary Detailed description: 7.13.3p7 states that the three standard streams are text. This makes it impossible to write programs like "cat" on systems where text and binary streams are not the same. There are a number of ways to provide this facility. Here is my prefered one: add a new paragraph to 7.13.5.4 before paragraph 3: If /filename/ is a null pointer, the /freopen/ function attempts to change the mode of the stream to that specified by /mode/, as if the name of the file currently associated with the stream had been used. =20 It is implementation-defined which changes of mode (if any) are permitted and under what circumstances. Public Comment Number PC-UK0063 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 7.13.9 Title: Provide a way to compare fpos_t values. Detailed description: There is no way to determine whether two fpos_t values represent the same position in a file. Therefore, it is not possible to do operations such as the following: - open a file - move through it, looking for some mark - note the position using fgetpos() - rewind - move through it again to the same position, using calls to fgetpos() to determine where you are, rather than relying on having made exactly the same sequence of reads and seeks Add a new function to 7.13.9: 7.13.9.X The fcmppos function Synopsis #include struct fcmppos fcmppos (fpos_t* pos1, fpos_t* pos2, FILE *stream) Description The /fcmppos/ function compares the values pointed to by /pos1/ and /pos2/, which must both refer to the stream /stream/. If either of the first two arguments is a null pointer, the result of a call to the =20 /fgetpos/ function on the stream is used instead. If the stream has been written to at any point before the later of the two positions, the behaviour is undefined. Returns The value returned is a structured type containing at least the following fields: int before; // Less than, equal to, or greater than zero // according // to whether /*pos1/ is before, at the same // location // as, or after /*pos2/ in the file. int mbstate; // Zero if and only if the two positions have the // same // multibyte parsing status. It will also be necessary to add /struct fcmppos/ to the start of 7.13. Public Comment Number PC-UK0064 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 7.13.8.1, 7.13.8.2 Title: Clarify the actions of fread and fwrite Detailed description: The exact behaviour of fread and fwrite are not well specified, particularly on text streams. In 7.13.8.1p2, add after the first sentence: For each object, /size/ calls are made to the /fgetc/ function and the results stored, in the order read, in an array of /unsigned char/ exactly overlaying the object. In 7.13.8.2p2, add after the first sentence: For each object, /size/ calls are made to the /fputc/ function, taking the values (in order) from an array of /unsigned char/ exactly overlaying the object. Public Comment Number PC-UK0065 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: various Title: What is the precision of floating point calculations ? Detailed description: DR 063 asked, for C89, what was the required precision of the results of the various floating point operators and functions. To date this has not been answered. I am not aware enough of the issues to be able to write a good answer myself, but references to IEC 559 and anne x F are not a sufficient solution. Public Comment Number PC-UK0066 Comment 1.=20 Category: Inconsistency Committee Draft subsection: various Title: The term "access" is not well defined. Detailed description: The term "access" is not well defined. From context, it sometimes appears to mean "read the value", and sometimes "read or write the value". This ambiguity sometimes makes it hard to understand what is actually meant. There needs to be a definition in clause 3, and all uses of the term need to be checked for the read-only / read-write problem. Probably the best approach is to define it as "read or write", and to find and fix the places where "read" is meant. An example where "access" clearly means "read" is in 6.5.3.1p5: A reference to a value means either an access to or a modification of the value. So "access" presumably means read but not write. But if so, then 6.5.3p6: What constitutes an access to an object that has volatile-qualified type is implementation-defined. must also exclude writing. But that would mean that what constitutes a write to a volatile object is *not* implementation-defined, but rather undefined ! Since this is obviously not the intent, there is a clear contradiction that needs resolving. There are plenty of other instances; for example, 6.3p6: ... If a value is stored into an object ... the type of the lvalue becomes the effective type of the object for that access ... where writing is clearly meant to be included. However, the point is not to address these individual cases but rather make the whole Standard consistent. Public Comment Number PC-UK0067 Comment 1.=20 Category: Other: tidy up (technically normative) Committee Draft subsection: 7.14 Title: tidy up definitions of macros Detailed description: In 7.14p3, change: EXIT_SUCCESS which expand to integer expressions which ... to: EXIT_SUCCESS which expand to integer constant expressions which ... and change: MB_CUR_MAX which expands to a positive integer expression whose value ... never greater than /MB_LEN_MAX/. to: MB_CUR_MAX which expands to a positive integer expression whose type is /size_t/ and whose value ... never greater than /MB_LEN_MAX/. This is not a constant expression: it may change whenever the locale changes. Public Comment Number PC-UK0068 Comment 1.=20 Category: Other: rewording to show consistency Committee Draft subsection: 7.14.6.2 Title: Change the description of div() to show consistency Detailed description: Change the description of the div function (7.14.6.2) to: Description The /div/ function computes the quotient and remainder of the division of the numerator /numer/ by the denominator /denom/. Returns The /div/ function returns a structure of type /div_t/, comprising both the quotient and the remainder. The structure shall contain the following members, in either order: int quot; // quotient, equivalent to (numer / denom) int rem; // remainder, equivalent to (numer % denom) If either part of the result cannot be represented, the behavior is undefined.[*] [*] The function is equivalent to: div_t div (int numer, int denom) { return (div_t) { .quot =3D numer / denom, .rem =3D numer % denom }; = } Alternatively, simply replace the entire description by the code in the suggested footnote. Public Comment Number PC-UK0069 Comment 1.=20 Category: Normative change to intent of existing feature Committee Draft subsection: Annex G Title: Reorganise annex G as two separate items Detailed description: Annex G currently gives a specification for IEC 559 compatible complex types *and* for imaginary types, all conflated. These are separate concepts which can each be useful. Annex G should be split into two separate parts. The first annex is "Imaginary Types" and is normative. It begins something like: This annex specifies imaginary types. An implementation shall either conform to all the requirements of this annex, and shall define the macro /_Imaginary_I/ in , or it shall not provide such types, shall not define the macro /_Imaginary_I/, and shall not define the keyword /imaginary/. It then includes all the imaginary type parts: G.2, G.3, G.4.1p1-3, G.4.2 (except for the words "and exceptions"), G.5p1, G.6. The second annex is "IEC 559 compatible complex arithmetic" and is normative. It is introduced with words like those in F.1, including: An implementation that defines __STD_IEC_559_COMPLEX__ conforms to the specification in this annex. It then includes G.4.1p4-7, G.4.2p2, G.5 except p1. Public Comment Number PC-UK0070 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 7.9 Title: Type-generic macros should be generally useful Detailed description: 7.9 introduces the concept of type-generic macros, but these are only available for a small range of mathematical functions. This facility should be made generally available so that they can be used for general programming. Public Comment Number PC-UK0071 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 6.8.2 Title: Clarify included file process Detailed description: 6.8.2p3 ends: If this search is not supported, or if the search fails, the=20 directive is reprocessed as if it read #include new-line with the identical contained sequence (including > characters, if any) from the original directive. The wording is technically incorrect, precisely because the original directive could contain angle brackets within the quotes whereas an h-char-sequence cannot. Better wording would be: If this search is not supported, or if the search fails, the directive is reprocessed as if it read #include new-line with the identical contained sequence from the original directive (if the q-char-sequence contains a > character, this is retained in the name searched for even though it could not appear in a true h-char-sequence). Public Comment Number PC-UK0072 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 7.11.1.1, 7.14.4 Title: _exit function Detailed description: As part of a working paper (N789), I suggested that C provide an _exit() function like that in POSIX, and signal handlers should be allowed to call this function. After further discussion, it would still appear that this function is useful and can be specified in a way that is completely conformant to POSIX. However, I have made some improvements to the wording in N789. Make the following changes: In 7.11.1.1 paragraph 5, change: or the signal handler calls any function in the standard library other than the /abort/ function or the /signal/ function=20 to: or the signal handler calls any function in the standard library other than the /abort/ function, the /_exit/ function, or the /signal/ function Add a new subclause 7.14.4.4 within 7.14.4 (Communication with the environment), renumbering subsequent subclauses. 7.14.4.4 The _exit function Synopsis #include void _exit (int status); Description The /_exit/ function causes normal program termination to occur, and control to be returned to the host environment. No functions registered by the /atexit/ function or signal handlers registered by the /signal/ function are called. The /_exit/ function never returns to the caller. The status returned to the implementation is determined in the same manner as for the /exit/ function. It is implementation-defined whether open output streams are flushed, open streams closed, or temporary files removed. Public Comment Number PC-UK0073 Comment 1.=20 Category: Other: clarification Committee Draft subsection: 6.5.5 Title: clarify order of evaluation of expressions within full declarators Detailed description: 6.5.5p3 states: The end of a full declarator is a sequence point. However, a full declarator can contain several expressions that require evaluation, and no ordering is stated. For example: int n; /* ... */ int v [++n][++n]; It is not clear whether this is undefined behavior (two modifications to n), unspecified behavior (which expression is evaluated first), or has a defined order. Change the cited wording to: The end of a full declarator is a sequence point; the various expressions within a full declarator are evaluated using the same rules for expression ordering as if they were combined into a single expression using the + operator. Public Comment Number PC-____ Comment 1. Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 6.2.2.3 Title: a pointer to an object should point to its first byte Detailed description: Add a requirement that a pointer to an object should point to its first byte when cast to a pointer to a character type. Without this requirement, functions such as memcpy() and fread() will not work as intended. In subclause 6.2.2.3 add a new paragraph after paragraph 7: If a pointer to an object is converted to a pointer to character type, the result points to the lowest addressed byte of that object. Successive increments of the result, up to the size of the original =20 object, yield pointers to the remaining bytes of the object. Public Comment Number PC-____ Comment 1. Category: Inconsistency Committee Draft subsection: various Title: problems with UCNs Detailed description: Further examination of UCNs shows that they have many problems associated with them, and in particular produce very different behaviour than would occur with C89. The following example was presented in comp.std.c by Antoine Leca and is summarised by me: What is the effect of the following code: #include #define str(s) #s int main(void) { printf (" # of <%s> is <%s>\n", "$", str ("$")); return 0; } Since $ is not part of the basic character set, this is not strictly conforming. However, assume that the implementation has a representation for $. Then, under C9X the output is clearly: # of <$> is <"$"> Under C9X, the output is probably one of: # of <$> is <"\u0024"> or # of <$> is <"\$"> At Translation Phase 1, both $s will be converted to \u0024, and so the source will become: #include #define str(s) #s int main(void) { printf (" # of <%s> is <%s>\n", "\u0024", str ("\u0024")); return 0; } When the # operator is applied as part of the expansion of str, the \ is doubled, producing the line: printf (" # of <%s> is <%s>\n", "\u0024", "\"\\u0024\""); in accordance with 6.8.3.2p2. Now, when TP5 is reached one has to decide whether the UCN is recognised first, generating: printf (" # of <%s> is <%s>\n", "\u0024", "\"\$\""); and undefined behaviour because of the escape sequence \$ - though I would expect at least some implementations to generate: # of <$> is <"\$"> - or else the escape sequence \\ is recognised first, generating the output: # of <$> is <"\u0024"> Neither, however, is what the naive programmer would expect, and neither interpretation allows a non-basic character to remain in a string that has the # operator applied to it. Another serious issue with UCNs is that they do not mix well with systems such as ISO 2022. Consider a situation where redundant shift sequences appear within string literals in source files. In C89 these sequences will be retained throughout the translation process and will appear when the literal is output by the program. In C9X the characters in the literal will be converted to UCNs and the shift sequences lost; a new set of, possibly different, shift sequences has to be added during TP5. For some applications this is a Quiet Change from C89. Public Comment Number PC-____ Comment 1. Category: Inconsistency Committee Draft subsection: 5.1.2.2.1, 5.1.2.2.3 Title: Alternate forms of main() are not well-enough defined Detailed description: 5.1.2.2.1 permits main() to have other implementation-defined types. These types might not include a return type of int. 5.1.2.2.3p1 reads: A return from the initial call to the /main/ function is equivalent to calling the /exit/ function with the value returned by the /main/ function as its argument.[10] If the } that terminates the /main/ =20 function is reached, the termination status returned to the host environment is unspecified. The first sentence is clearly nonsense if the return type of main() is not convertable to int. Change 5.1.2.2.3p1 to: If the return type of the /main/ function is a type compatible with /int/, then a return from the initial call to the /main/ function is equivalent to calling the /exit/ function with the value returned by =20 the /main/ function as its argument.[10] If the } that terminates the /main/ function is reached, or the return type of the /main/ function is not a type compatible with /int/, the termination status returned =20 to the host environment is unspecified. Public Comment Number PC-UK0077 Comment 1.=20 Category: Normative change to feature Committee Draft subsection: 6.1.2.4, 6.6.4.2, 6.6.6.1, 7.10.2.1 Title: Fix semantics of jumps in relation to VLAs NOTICE - this is a replacement for PC-UK0045, which is withdrawn. Detailed description: Consider the code: { int n =3D 1; label: int v [n]; /* ... */ if (n++ < 10) goto label; } The constraint on 6.6.6.1 does not forbid this jump, but the storage for v cannot be allocated on block entry as described in 6.1.2.4p3. Consider the code: { int n =3D 1; goto label; int v [n]; label: /* ... */ } This also does not violate the constraint, but the size of the array is never determined. Consider the code: int n; /* ... */ if (n > 0) goto label; { n =3D 1; label: int v [n]; /* ... */ } This is forbidden by 6.6.6.1, but its meaning is clear and sensible. The intent of the constraint in 6.6.6.1 is clearly to prevent a jump into a block from skipping a VLA declaration, but as can be seen it does not have this effect in practice. Similarly, the wording of 6.1.2.4p3 for VLAs is obviously an attempt to adapt the previous wording, but it does not have the right effect. Previous discussion within WG14 appeared to reach the conclusion that: - jumping into the scope of a VLA should violate a constraint; - jumping out of the scope of a VLA causes storage to no longer be reserved, even if the block containing the declaration has not been left; and these rules seem eminently practical. To do this: In 6.1.2.4p3, replace: Storage is guaranteed [...] execution of the block ends in any way. with: For objects that do not have a variable length array type, storage is guaranteed to be reserved for a new instance of such an object on each entry into the block with which it is associated; the object initially has indeterminate value. If an initialization is specified for the value stored in each object, it is performed each time the declaration is reached in the execution of the block; otherwise the value becomes indeterminate each time the declaration is reached. Storage for the object is no longer guaranteed to be reserved when execution of the block ends in any way. For objects that have a variable length array type, storage is guaranteed to be reserved for a new instance of such an object each time the declaration is reached in the execution of the program. The initial value is indeterminate. Storage for the object is no longer guaranteed to be reserved when execution of the program leaves the scope of the declaration [*]. [*] Leaving the innermost block containing the declaration, or jumping to a point in that block or an embedded block before the declaration, leaves the scope of the declaration. In 6.6.4.2p1, replace the first sentence with: The controlling expression of a /switch/ statement shall have integer type. If the /switch/ statement causes a jump to within the scope of an identifier with variably modified type, the entire /switch/ statement shall be within the scope of that identifier [*]. [*] That is, the declaratio either preceeds the /switch/ statement, or it occurs after the last /case/ or /default/ label that is in the block containing the declaration and is associated with the /switch/. In 6.6.6.1p1, replace the second sentence with: A /goto/ statement shall not jump from outside the scope of an identifier with variably modified type to inside the scope of that identifier. In 7.10.2.1, change the last sentence of paragraph 2 from: If there has been no such invocation, or if the function containing the invocation of the /setjmp/ macro has terminated execution [192] in the interim, the behavior is undefined. to: If there has been no such invocation, or if the function containing the invocation of the /setjmp/ macro has terminated execution [192] in the interim, or if the invocation of the /setjmp/ macro was within the scope of an identifier with variably modified type and execution has left that scope in the interim, the behavior is undefined. Public Comment Number PC-UK0078 Comment 1.=20 Category: Normative change to existing feature retaining the original inten= t Committee Draft subsection: 5.1.1.2, 5.2.1 Title: Universal character name handling Detailed description: A nasty little problem arises in code like the following: #define str(a) #a str("$") In phase 1, the second line is mapped to str("\u0024") or perhaps str("\U00000024"). In phase 4, this will be mapped to #"\u0024" and (by 6.8.3.2 The # operator paragraph 2) to "\"\\u0024\"". In phase 5, this will be mapped to the execution character set, but there is no explicit statement of the priority of mapping escape sequences and universal character names. So it is probably mapped to the sequence of characters: '"','\\','u','0','0','2','4','"','\0' but (if universal character names take priority) to '"','\$','"','\0' which leads to undefined behaviour. In either case, this is a quiet change from C89. There are quite a lot of similar ambiguities commented on elsewhere, that need some sort of resolution. The more that I think about it, the less that I think the problems with these can be solved by tweaking, so here is a radical solution that I believe maintains all the functionality and resolves the problem. It is based on the principle that universal character names have a similar purpose to trigraphs and therefore should be treated similarly. I think that the following changes are all that are NECESSARY, but some more cleaning up may be desirable. 5.1.1.2 Translation phases Phase 1 should be rewritten as: 1. Physical source file multibyte characters are mapped to the source character set (introducing new-line characters for end-of-line indicators) if necessary. Secondly, trigraph sequences are replaced by corresponding single-character internal representations. Thirdly, universal-character-na= mes are replaced by the corresponding single-character internal representations. Phase 5 should be rewritten as: 5. Each source character set member and escape sequence in character constants and string literals is converted to a member of the execution character set. Footnote 6 should be rewritten as: 6. The process of handling extended characters is specified in terms of mapping to an single-character encoding that includes the union of the whole source character set and the characters specified by ISO/IEC 10646-1, and, in the case of character literals and strings, further mapping to the execution character set. In practical terms, however, any internal encoding may be used, so long as an actual character encountered in the input, and the same character expressed in the input as a universal-character-name (i.e., using the \U or \u notation), are handled equivalently. Constraint 2 could be deleted, as it is now unnecessary. 5.2.1 Character sets A new paragraph 6 should be added: 6. Source cha acters shall be encoded as if the source character set included the whole of ISO/IEC 10646 as single characters, using an unspecified mapping to integral values (except as specified above). Public Comment Number PC-UK0079 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 5.1.1.2 Title: Source line splicing Detailed description: One of the obscurer traps in C89 is that trailing spaces in C programs are significant in precisely one context: following the '\' used to splice physical source lines in translation phase 2. This causes considerable trouble on systems that support fixed-format records, because the implementation can treat those spaces as part of the end-of-line indicator, but need not do so. Many implementors think that the standard mandates trailing spaces to be regarded as significant. I suggest adding t= he following: Recommended Practice While mapping the physical source file to the source character set during phase 1, an implementation should regard an end-of-line indicator as being a maximal sequence of horizontal white space terminated by a single end-of-record indicator including any associated vertical layout directives. E.g. on a system that uses the same I/O model as C, "A \t \n\fB\n\n\t \tC\n" should be mapped to "A\nB\n\n\t \tC\n". Public Comment Number PC-UK0080 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 5.1.1.2 Title: Universal character names and #include Detailed description: I am afraid that universal character names have introduced some incompatibilities with C89, as in directives like '#include "a$b.h"'. This was defined in C89, but becomes undefined in C9X (i.e. it maps to '#include "a\u0024b.h"'). This is a deceptive trap, and one that will cause serious problems on some systems, as "$" is a fairly common character in header names. An evil variant of this is '#include "\udefault\a$b.h"' on MS-DOS and derivative systems. This maps to "\udefault\a\u0024b.h", which is either handled as such or mapped to "?ult\a$b.h", where '?' is whatever '\udefa' is. The current wording implies that one or the other approach should be used, though I don't think that it actually forbids mapping back to "\udefault\a$b.h". Note that these are quiet changes. In C89, "$" can be used in a program as a normal character, subject ONLY to it being a member of the basic source (and, if necessary, the basic execution) character sets.=20 In C9X, it has an implementation-defined value that need not be that of any character. I suggest adding the following to help with the header and pragma problems: Whether a universal character name or character not in the the basic source character set is interpreted during phase 4 in its universal character name form or as a single character is implementation-defined. Under this circumstance alone, an actual extended character encountered in the input, and the same extended character expressed in the input as a universal-character-name, need not be handled equivalently. Recommended practice An implementation should, when appropriate, interpret characters in their input form during phase 4. A good implementation will diagnose uses when this is not the case, or where there is potential ambiguity. Public Comment Number PC-UK0081 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 5.1.1.2, 6.1.3.4, 6.1.4, Annex B Title: Universal character names and character constants Detailed description: If both the basic source and basic execution character sets include "$" (which is implementation-defined in both C89 and C9X), the following is true in C89: #include #if '$' <=3D UCHAR_MAX But this is NOT required by the current wording of paragraphs 10 and 11 in C9X, which leaves this case implementation-defined even if both the basic source and basic execution character sets include '$'. This is because the '$' expands to '\u0024', and the wording in those sections makes it quite clear that '\u0024' is neither a single character nor an escape sequence. Note that this affects ONLY translation phase 4, because phase 5 deals with the problem. I suggest moving "universal-character-name" in the Syntax section of 6.1.3.4 Character constants from being an entry in "c-char" to being one in "escape-sequence". This also needs to be done in 6.1.4 String literals and both places in Annex B, of course, but I can't see that it introduces any problems in any of them or other sections. Public Comment Number PC-UK0082 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 5.2.1 Title: Source character set values Detailed description: While investigating universal character names, I have realised that there does not seem to be any requirement on the characters in the source character set to have positive values, or even to be non-zero! 6.8.1 Conditional inclusion paragraph 3 adds a little imple mentation-definition,= but not much. I suggest replacing the following sentence in paragraph 3: In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous. by: In both the source and execution basic character sets, the value of each character in the above list shall be strictly positive, the value of zero shall not correspond to any printing character, and the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous. Public Comment Number PC-UK0083 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 5.2.1.2 Title: Multibyte characters and C89/C9X changes Detailed description: This appears to be a relic of C89, as far as the source character set is concerned, and is utterly baffling in the context of C9X. Here are some of the problems: 1) Paragraph 1 refers to multibyte characters in the source character set, but 5.1.1.2 bullet one refers to physical source file multibyte characters being mapped to members of the source character set. 2) The second bullet says that that the presence, meaning, and representation of any additional characters is locale-specific. But locale is an execution concept! I cannot find anything anywhere else in the standard that describes the concept of locale during compilation. 3) The fourth bullet says that a byte with all bits zero shall be interpreted as a null character, but the source character set is not required to include a null character (5.2.1. paragraph 2). 4) Paragraph 2 describes how multibyte characters must fit within various syntactic objects. But tokenisation does not occur until translation phase 3, and multibyte characters are mapped to universal character names in phase 1! 5) And, in any case, at what state should this be true? After phase 3, or after phase 4? Token concatenation and stringisation could cause trouble here, especially if a multibyte character in a identifier changed the shift state (ugh). I suggest replacing paragraph 1 by: 1. The source may be encoded using multibyte characters, used to represent members of the extended character set. The execution character set may also contain multibyte characters, which need not have the same encoding as for the source. For the execution character set, the following shall hold: Paragraph 2 should be replaced by: Recommended practice If the source is encoded using multibyte characters, a representation compatible with some conforming multibyte execution character set should be used. Public Comment Number PC-UK0084 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 6.1.2 Title: Identifier lengths Detailed description: Paragraph 6 is ambiguous. Do the 31 and 63 character limits include universal escapes as one character, or as their source length? This needs specifying clearly, one way or the other, or there will be serious confusion. I cannot suggest wording, as I do not know the committee's intentions. Public Comment Number PC-UK0085 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 5.2.2, 6.1.3.4 Title: The escape character Detailed description: I still don't understand why '\e' isn't provided for ESC. The answer given in the C89 Rationale (that is is not available in EBCDIC) is quite simply wrong - evidence available upon request. It could clearly be added upwards compatibly but, equally clearly, its specification has to be that it does something implementation-defined (which is precisely what ASCII and ISO 646 say.) Public Comment Number PC-UK0086 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 6.8.1 Title: Invalid but skipped pre-processor directives Detailed description: Programs of the following form currently cause serious arguments, and I cannot see that the ambiguity has been resolved: #if 0 =3D=3D 1 #axolotl #endif Is this permitted or is it not? I.e. is the undefined pre-processing directive "#axolotl" an error? Most compilers assume that it should be quietly ignored, but a few reject the above program fragment. Assuming that it should be ignored, I suggest a footnote in 6.8.1 Conditional =20 inclusion after "the other preprocessing tokens in the group." along the lines of: 124a Thus unrecognised preprocessing directives in a group that is skipped are ignored and do not cause an error. Alternatively, if it should be an error, there should be some rewording to indicate that. Public Comment Number PC-UK0087 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 7.4.4 Title: Macros for format specifiers Detailed description: These are all very well, but this is a major quiet change and not a welcome one, either. In C89, long is guaranteed to be the longest integer type, and it is possible to cast to long and use a simple format to print any integer. C9X abolishes this, and will break many programs. Even when they are rewritten, their formats will become unreadable. I suggest one of two solutions: 1) Restore the requirement that long is the longest integer type or: 2) Introduce %md, %mu, %mx etc. for the ***MAX forms to alleviate the pain, as has been suggested. This is still a change, but should cause less opposition. Doing BOTH enables programmers to convert their code to using intmax_t during the life of C9X, which leaves the option open for a future revision of the C standard to reintroduce 'long long' with minimum incompatibility, and is what I should prefer. The current proposal forces immediate and serious incompatibility, breaks existing and important conforming code, and makes it impossible to convert it cleanly to C9X. Public Comment Number PC-UK0088 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.13.8 Title: Direct input/output functions Detailed description: These have caused considerable confusion to both users and implementors since they were introduced. What DO they do on text streams on non-Unix systems? Experience shows that they often do something unhelpful - such as fwrite writing files that cannot be read back in again by fread without loss of information. Note that the problem is not in the actual data transfer, but in the problem of how to convert an unspecified block of storage to characters and back again. In particular, 7.13.2 Streams states that only some sequences of characters can be written out and read back in again - actually, there are even more constraints than that (e.g. record lengths). Some non-Unix implementations have converted the data to unsigned characters and then to hexadecimal, but most just write the raw characters and let the chaos ensue. And chaos is precisely what the programmer gets, in general. This ambiguity has caused trouble for long enough. I suggest adding one or other of the paragraphs: An implementation may define that these functions are not available for text streams. If that is the case, calling one of these functions on a text stream shall have no effect except to set errno to an =20 implementation-defined positive value and return EOF. or: It is implementation-defined how the storage is converted to and from characters for I/O to and from text streams. The implementation shall ensure that one or more objects of any type can be written out using the fwrite function and read back in to objects of the same type using the fread function with the same value of size without loss of information. Public Comment Number PC-UK0089 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.13.3 Title: Requiring line buffering on stderr Detailed description: Paragraph 7 is unimplementable under many systems. There are systems that support only full buffering for some classes of file - including Unix! Try writing stderr to fixed-block tapes on Unix systems where write() will not reblock, for example. It is also COMPLETELY impossible to implement under MVS, CMS and probably VMS, as buffering is an inherent property of the type of file and cannot be changed by the connexion. It is not reasonable to require that every single MVS implementation ignores the C standard (even if in such a minor respect.) I suggest changing the wording to: ... When opened, the standard error stream is not fully buffered, except in implementation-defined circumstances where only full buffering is available; ... Public Comment Number PC-UK0090 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 7.13.5 Title: Determining whether a stream is interactive Detailed description: An old problem with the C library is that some essential functions in the base document operated on Unix file descriptors and not streams. Most of these have been added to C in 'stream' form, but isatty() has not. This is a serious omission as it means that there is no way for a portable program to determine whether a stream is 'interactive' or not, despite the fact that such semantics are defined in 7.13.3 Files. The following specification has been implemented several times, under both MVS and Unix, and probably other systems. I suggest adding something like the following: 7.13.5.7 The fisatty function Synopsis 1 #include int fisatty(FILE *stream) Description 2 The fisatty function indicates whether the stream refers to an interactive device, in the sense used by section 7.13.3 to determine whether a stream is opened fully buffered or not. Returns 3 The fisatty function returns a nonzero value if and only if the stream can be determined to refer to an interactive device. =20 [ Incidentally, this state can change during the lifetime of a stream under MVS and some other systems, but I suggest ignoring that little nasty! The above wording should be adequate for both the changing and normal cases. ] Public Comment Number PC-UK0091 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 7.13.5 Title: Truncating a file Detailed description: A frequently missed feature of C is the ability to truncate a file; all that the standard provides is the ability to clear a file and rewrite it from the beginning. The following specification deliberately does not attempt to follow any common existing practice, but is worded so that it should be easy to implement on most important systems and requires a near-minimal specification (so as to maintain consistency with other parts of the standard.) I have implemented something very close to the following specification on both MVS and Unix. I suggest adding something like the following: 7.13.5.8 The ftruncate function Synopsis 1 #include int ftruncate(FILE *stream) Description 2 The ftruncate function truncates the file at the current position. All characters in the file beyond the current position become inaccessible, and the logical end of file is set to the current position. = All other properties of the file and stream are unchanged, unless an error occurs. 3 A call to the ftruncate function is an output operation (7.13.5.3). Returns 4 The ftruncate function returns zero if the file was successfully runcated, or EOF if the stream was open for reading or any other rrors were determined. Public Comment Number PC-UK0092 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.13.9.2, 7.13.9.3, 7.13.9.5, 7.13.10.1 Title: Hard I/O errors and EOF Detailed description: 7.13.9.2 The fseek function, 7.13.9.3 The fsetpos function, 7.13.9.5 The rewind function and 7.13.10.1 The clearerr function all make the assumption that the end-of-file and error indicators can be cleared, and still have a useful specification. This is not true, even under Unix. Consider EOF from a pipe or an I/O error from a remote socket, for example. Furthermore, many implementations already support an enhanced interface (described below), and some programs rely on it, so C9X should be updated to reflect existing practice. It is a great pity that two of them are void functions, but that cannot be changed now, so I suggest adding the following paragraph to the first two: =20 If either of the end-of-file or error indicators are set, and the implementation can determine that the condition that caused them to be set cannot be cleared, it shall set an implementation-defined positive value in errno and return a nonzero value. and the following to the second two: If either of the end-of-file or error indicators are set, and the implementation can determine that the condition that caused them to be set cannot be cleared, it shall set an implementation-defined positive value in errno. Public Comment Number PC-UK0093 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 7.13.10 Title: I/O error diagnosis function Detailed description: One of the worst aspects of programs written in standard C is that application diagnostics are so poor, which is partly because of the requirement for all of them to be mapped into a single integer error code, and then back to text. Many systems can provide much more information, and a standard function is needed so that portable applications can make use of that. By far the most important area is I/O, so I suggest adding the function: 7.13.10.5 The ioerror function Synopsis 1 #include char *ioerror(FILE *stream) Description 2 The ioerror function maps the error state of the stream to a message string. The string may contain newline characters, may include information that is not simply a description of the reason for the failure, and apparently identical error states may map to different strings. 3 The implementation shall behave as if no library function calls the ioerror function. Returns 4 The ioerror function returns a pointer to the string if the error flag is set for the stream. If the error flag is not set for the stream, it is unspecified whether a null pointer, an empty string or some =20 informative text is returned. The array pointed to shall not be modified by the program, but may be overwritten by a subsequent call to the ioerror function. [ Note that I have left the message unspecified rather than implementation defined, because the main object is to get away from fixed error messages and allow the inclusion of dynamic data. Requiring implementation definition would discourage this, because the message will often be received from another system component (e.g. a socket library) and hence be unknown to the C run-time system. I have implemented the above specification, and can hence claim prior art! ] Public Comment Number PC-UK0094 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 7.14.2.2 Title: The srand function Detailed description: The example has caused an immense amount of trouble. It is an extremely poor generator, but several vendors have insisted on implementing it because it is in the standard. I do NOT recommend including ANY algorithm in the standard as, at best, it is a hostage to fortune. If people really insist on including a particular generator, PLEASE contact me directly (nmm1@cam.ac.uk) for comments on the algorithm. I suggest adding the following: Recommended practice An implementation should provide a better random number generator, and not use this example. Public Comment Number PC-UK0095 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 7.14.6 Title: BCPL muldiv for multi-precision arithmetic Detailed description: The div functions have no unsigned forms, which can be a serious inconvenience for things like radix conversion and multiple length arithmetic (including some cryptographic algorithms.) There is also the vexed question of whether C has to support 64-bit integers and whether it should support 128-bit integers. It would be extremely nice for C to enable programmers to use extended integer arithmetic, without forcing every compiler writer to have to build it in. Considerable experience with BCPL and other languages is that double precision integer arithmetic can be coded efficiently in a high level language, with the exception of two primitives. These are a NxN -> 2N multiply and a 2N -> N,N divide (giving quotient and remainder), most of the functionality of which can be provided by a single composite form (i.e. NxN mod N -> N,N). BCPL had a MULDIV function, which did something like this, but it got lost somewhere in the conversion to C, and was replaced by the much more limited div function. Experience with MULDIV suggests that it could be improved for this purpose, and the improved specification is proposed here. It includes the functionality of the div functions, so there is little point in providing unsigned versions of those. It needs the obvious changes at the head of this section to the descriptions of div_t, ldiv_t and lldiv_t, and the addition of udiv_t, uldiv_t and ulldiv_t. The functions should have specifications like the following: 7.14.6.7 The muldiv function Synopsis 1 #include div_t muldiv(int a, int b, int c, int base); Description 2 The muldiv function computes the quotient and remainder of the division of the numerator a * b + c by the denominator base; if base is zero, the value INT_MAX+1 is used instead. The returned quotient is the algebraic quotient with any fractional part discarded. 3 If base is negative or if the result cannot be represented, the behaviour is undefined; otherwise quot * base + rem shall equal a * b + c. This equality shall hold as if the expressions were calculated from the values of quot, base, rem, a, b and c without overflow. Returns 4 The muldiv function returns a structure of type div_t, comprising both the quotient and the remander, as for the div function (7.14.6.2). [ Note that the reason for allowing error conditions to lead to undefined behaviour rather than flagging them is that this function is often needed in the core of a computationally intensive algorithm. RSA encryption is one example. ] 7.14.6.8 The lmuldiv function Synopsis 1 #include ldiv_t lmuldiv(long int a, long int b, long int c, long int base); Description 2 The lmuldiv function is equivalent to the muldiv functi =3Don, expect that the arguments and the members of the returned structure (which has type ldiv_t) all have type long int and the value used if base is zero is LONG_MAX+1. 7.14.6.9 The llmuldiv function Synopsis 1 #include lldiv_t llmuldiv(long long int a, long long int b, long long int c, long long int base); Description 2 The llmuldiv function is equivalent to the muldiv function, expect that the arguments and the members of the returned structure (which has type lldiv_t) all have type long long int and the value used if base is zero is LLONG_MAX+1. 7.14.6.10 The umuldiv function Synopsis 1 #include udiv_t umuldiv(unsigned int a, unsigned int b, unsigned int c, unsigned int base); Description 2 The umuldiv function is equivalent to the muldiv function, expect that the arguments and the members of the returned structure (which has type udiv_t) all have type unsigned int and the value used if base is zero is UINT_MAX+1. 7.14.6.11 The ulmuldiv function Synopsis 1 #include uldiv_t ulmuldiv(unsigned long int a, unsigned long int b, unsigned long int c, unsigned long int base); Description 2 The ulmuldiv function is equivalent to the muldiv function, expect that the arguments and the members of the returned structure (which has type uldiv_t) all have type unsigned long int and the value used if base is zero is ULONG_MAX+1. 7.14.6.11 The ullmuldiv function Synopsis 1 #include ulldiv_t ullmuldiv(unsigned long long int a, unsigned long long int b, unsigned long long int c, unsigned long long int base); Description 2 The ullmuldiv function is equivalent to the muldiv function, expect that the arguments and the members of the returned structure (which has type ulldiv_t) all have type unsigned long long int and the value used if base is zero is ULLONG_MAX+1. Public Comment Number PC-UK0096 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.11.1.1 Title: Signal handlers and signal classes Detailed description: The wording of paragraph 3 is better in C9X than that in C89, but still bears little relationship to reality. Even under Unix, returning from a SIGINT handler is as likely to cause trouble as returning from a SIGFPE, SIGILL or SIGSEGV one. One reason for this problem under Unix is that ANY signal causes some system calls to be aborted, and many of those do not provide enough information to enable them to be restarted transparently; socket I/O is a particularly grim area in this respect, as an aborted read() or write() does not reliably indicate how much data was successfully transferred (see POSIX.1). This problem is one of the reasons that Unix utilities occasionally crash with a SIGSEGV after having trapped and recovered from another signal. I could go into some length about consistency problems in compiled code, even though I know only a few architectures at that level, but I can say that the problems are getting worse and many of them are blurring the distinction between synchronous and asynchronous signals (not that there every has been a clear boundary). Consider the latest 'fad', for example: multiple CPU threads of execution within a single software thread (or even software threads), and then consider which thread should handle a signal and what it should do about the others while doing so. These problems often mean that it is HARDER to trap and recover from an asynchronous signal than from one like SIGFPE (which at least has a single associated thread). And, lastly, there are many systems where returning from a sys tem-generate= d signal of the SIGABRT variety is an absolute no-no! I suggest replacing the last sentence by the much simpler and more general: The implementation may define circumstances in which returning from a signal handler leads to undefined behaviour; otherwise the program will resume execution at the point that it was interrupted. Public Comment Number PC-UK0097 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 5.1.2, 7.11 Title: Reliable signal handling Detailed description: Section 7.10.2.1 The longjmp function has removed any statement about longjmp being supported in signal handlers. As it didn't work anyway, for other reasons, this is a major quiet change that has no effect! But some people will be unhappy. The following is a possible change that would improve (though not resolve) quite a lot of the problems. It is couched in terms of recommended practice, where an implementation is required to say whether it follows such practice. The handling of system-generated signals is a very nasty area indeed, and few (if any) languages get it 'right'. Most simply opt out and leave it undefined. Unfortunately, the specification in C89 is both extremely hard to implement successfully (even under Unix) and is almost unusable in portable programs because of the number of exclusions necessary to make it implementable at all. There have been several heated debates on comp.std.c on this. There are some well-known problems with returning from signal handlers, but there are as many or more with jumping out of handlers. In particular, all updated non-volatile global variables become undefined (see the "least requirements" section in 5.1.2.3). And I can witness that this corresponds precisely with many or most implementations. Lastly, and most cogently, C9X has (correctly) removed any that jumping out of signal handlers is supported! In that sense, C9X has introduced a major quiet change, but (as mentioned above) the facility never was usable. This proposal defines recommended practice that restores the functionality that was intended by C89. This wording should be added to section 5.1.2 Execution environments to encourage implementors to do better in a defined and consistent fashion (thus enhancing portability), without making life impossible for them. It should be possible to implement usefully under almost all modern systems with reasonable signal handling (including MVS and Unix). The author has considerable experience of precisely this area under MVS, and a fair amount under Unix and several other systems. Note that I am assuming that the implementation can provide signal-safe library functions, except in cases where efficiency is critical. This can be done on every modern architecture that I know of, with minimal overhead (though with possible storage leaks etc.) The cases where it would be seriously inefficient are permitted to be handled differently by the following description. I know that some vendors will say that implementing a safe malloc() is hard. But I have done that. It isn't hard - it just takes thought and care. In fact, most of the exclusion sections below are unnecessary, but were put there to prevent an implementor from having to jump through hoops if the system is more than usually perverse. If people want to ask me questions directly, my Email address is nmm1@cam.ac.uk.=20 All of the following text is proposed for inclusion. 5.1.2.4 Reliable signal handling A conforming implementation shall define whether it supports reliable signal handling and, if so, any environment that needs to be specified during compilation or execution or both to select that support and how a conforming program can determine that it is executing in this state. When such conditions are satisfied, the program will be described as being in reliable signal mode.999 999. The least requirement on a conforming implementation is that it defines that it does not support reliable signal handling. The remainder of this section applies only to programs in reliable signal mode, and defines or implementation-defines semantics for behaviour that would otherwise be undefined. Nothing in this section changes the validity or meaning of any strictly conforming program, or any program not executing in reliable signal mode. A facility is supported by an implementation if it has the effect described in this section or elsewhere in the standard. The behaviour of conforming programs is well-defined for signals raised by calls to the raise and abort functions, so any reference to signals in this section should be taken to refer to system-generated signals. An implementation shall define any restriction on the handlig of signals raised by calls to the raise and abort functions that is not shared by the handling of system-generated signals. 5.1.2.4.1 Extra defined semantics If a static storage duration variable of type volatile sig_atomic_t has a defined value at one sequence point and is updated solely between that and the following sequence point by being assigned defined values, then then at all times between those sequence points (inclusively) it shall contain one of its initial or assigned values. How many times any such assignments occur (if at all) and in what order is unspecified. It is implementation-defined whether static duration variables of type volatile void * have the same consistency semantics as static duration variables of type volatile sig_atomic_t (as describe in the previous paragraph), and whether any special environment must be specified for this to be the case. It is implementation-defined whether nested signals (that is signals=20 raised during the execution of a signal handler) are supported. This support may be signal-dependent and there may be other=20 implementation-defined constraints. It is implementation-defined whether multiple signals (that is a second signal raised before a previous one has been ignored or its signal handler has started executing) are supported and, if so, whether a second signal will be suspended until after the first signal has been processed or whether the second one will handled as a nested signal. This support may be dependent on which signals occur and in which order, and there may be other implementation-defined constraints. It is implementation-defined whether signals raised during the execution of functions registered by atexit are supported. 5.1.2.4.2 Signal sequence points The execution of the setjmp macro after the arguments have been evaluated shall be a special sequence point, described in this section as a signal sequence point. The sequence points following the evaluation of the arguments of calls to the longjmp, signal, raise, abort or exit functions shall be signal sequence points. If a signal handler is called as the result of raising a signal, there shall be a signal sequence point following the creation of the argument list for the call to the signal handler. If a signal handler is called as the result of raising a signal and it returns (whether by executing a return statement or by reaching the end of the function), then there shall be a signal sequence point immediately following the return from the handler. It is implementation-defined whether there are any signal sequence points associated with a call to the system function. An implementation shall satisfy the following conditions at a signal sequence point: * All the conditions for a sequence point shall be satisfied. * Unless the signal sequence point is associated with the call to a signal handler, all objects with static storage duration and all automatic objects defined without the register attribute prior to the latest entry to the function that contains the signal sequence point shall be stable in the sense that previous evaluations are complete and subsequent evaluations have not yet occurred. * All signals raised as a direct consequence of executing previous code shall have been handled, and ones raised as a direct consequence of executing subsequent code shall not yet have had any effect on the program. Signals raised as the result of computational exceptions are direct consequences of executing the code, but those raised as the result of operating on files may be indirect, except as restricted by the following paragraph. * All previous calls of the remove, rename, fopen, freopen, fflush and fclose functions shall have been completed and subsequent calls shall not have been started, and all input and output to interactive devices required by the standard shall have taken place. The intention is that the actions of these calls shall have been synchronised with the environment. 5.1.2.4.3 Handling reliable signals If a system-generated signal is raised, then any call to a signal handler shall behave as if it were invoked by a simple call to the raise function, except for the following: * The call to the raise function need not correspond with a well-defined location in the code, except as defined in 5.1.2.3 and the following constraints. * The values of any volatile objects updated since the previous sequence point are indeterminate, except for static storage duration variables of type volatile sig_atomic_t updated only by assigning defined values, and those of type volatile void * if the implementation defines them to have the same semantics. * The values of any non-volatile objects updated since the previous signal sequence point are indeterminate, including those objects and system variables that the standard defines may be updated by any of the library functions called since that signal sequence point. * If any library function that returns a pointer to storage that may be overwritten by subsequent calls (such as the getenv function, 7.14.4.4, or the time conversion functions, 7.16.3) has been called since the previous signal sequence point, the contents of any such storage returned by any previous call are indeterminate. * If any library function that uses internal storage or state (such as the strtok function, 7.15.5.8, the multibyte character functions, 7.14.7, or the multibyte to wide-character conversion functions, 7.19.7) has been called since the previous signal sequence point, the contents of any such internal storage or state are indeterminate. They may be reset to a defined state by a call that is defined to initialise such storage or state (e.g. by calling the strtok function with a non-null pointer in its argument s1 or by calling the mblen function with a null pointer in its argument s). * If the setlocale function has been called since the previous signal sequence point, the locale is indeterminate and the effect of calling any library function that uses the locale is undefined. The locale may be set to a defined state by a call to setlocale with first argument LC_ALL and a second argument that is not NULL. * If any of the floating-point control modes have been modified since the previous signal sequence point, using the functions defined in 7.6 or otherwise, the floating-point environment will be indeterminate on entry to the handler. An implementation may define other circumstances under which the floating-point environment is indeterminate on entry to a signal handler. The floating-point environment may be set to a defined state by a call to fesetenv with an argument of FE_DFL_ENV. * If any of the floating-point control modes are modified during the execution of a signal handler, the state of the floating-point environment upon leaving the handler is implementation-defined and may be defined to be indeterminate. The floating-point environment may be set to a defined state by a call to fesetenv with an argument of FE_DFL_ENV. * An implementation may define circumstances under which the floating-point exception flags are indeterminate upon entry to a signal handler. * Upon leaving a signal handler by return or by calling the exit function, it is implementation-defined whether the floating-point exception flags are restored to the values that they had immediately before the signal was raised, or whether they preserve the values that they had immediately before leaving the signal handler. * Upon leaving a signal handler by calling the longjmp function, it is implementation-defined whether the floating-point exception flags are restored to the values that they had immediately before the signal was raised, whether they are restored to the values that they had immediately before the setjmp macro was executed, or whether they preserve the values that they had immediately before leaving the signal handler. * Upon leaving a signal handler by calling the longjmp function, the behaviour is undefined unless the jump buffer was set up either at a time when no signal handler was executing or earlier in the execution of signal handler for the current signal. An implementation may define other circumstances under which leaving a signal handler by longjmp leads to undefined behaviour. * If the signal function (7.11.1.1) has been called for a particular signal since the previous signal sequence point, the signal handler for that signal is indeterminate and the effect of raising that signal is undefined. It may be reset by another call to the signal function for that signal, but the return value will be indeterminate. * The state of any file object that has been accessed other than by calls to the ferror or feof functions since the previous signal sequence point is indeterminate. * If the rand or srand function (7.14.2) has been called since the previous signal sequence point, the effect of calling the rand function subsequently is undefined. The rand function may be reset to a defined condition by a call to the setrand function. * If the realloc function (7.14.3.4) has been called since the previous signal sequence point, the state of the storage pointed to by its argument ptr is indeterminate. * If the atexit function (7.14.4.2) has been called since the previous signal sequence point, it is undefined whether the function is registered. * If a signal is raised during a call to the system function (7.14.4.5), the behaviour is implementation-defined. Public Comment Number PC-UK0098 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 4 Title: Compliance footnote Detailed description: Paragraph 3 footnote 4 is somewhat misleading, as people have pointed out. My view is that the footnote could simply be scrapped, with benefit all round. Public Comment Number PC-UK0099 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 5.1.2.2.3 Title: Program termination Detailed description: The function main is very peculiar in several respects, and a great many users get confused by what forms of return lead to defined behaviour. I think that dropping off the end of main() in a hosted implementation should be defined to behave as if it were 'return 0;', which is clearly upwards compatible with the existing state. A far better solution would be to require non-void functions to return with a value, but that is more controversial. Public Comment Number PC-UK0100 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.1.2 Title: Cross-reference error Detailed description: Paragraph 2 refers to Annex H, but it should refer to Annex I. Public Comment Number PC-UK0101 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.1.2.2 Title: Linkages of identifiers Detailed description: The wording of paragraph 4 is thoroughly confusing, because the expression "the A of B becomes the A of C" is culture-dependent. In the form of English that I am most used to, it usually means "the A of B is copied to the A of C", and that is NOT what is meant here. I suggest that the word "becomes" is replaced by "is taken from". Public Comment Number PC-UK0102 Comment l Category: Other (suggestion for deprecated practice) Committee Draft subsection: 6.1.2.2 Title: Linkages of identifiers Detailed description: Linkages were one of the nastiest and least-defined aspects of K&R C; almost every early ISO/ANSI compiler got the C89 semantics wrong in many and varied ways. While the conformance of implementations has improved, paragraphs 4 and 5 hide some extremely deceptive traps for the programmer; in particular, the fact that 'extern' does not necessary imply external linkage, even on definitions, and can even imply the converse. A large number of these traps are there mainly to support upwards compatibility for code written for K&R compilers that did not allow the static keyword in declarations that were not definitions (and so subverted the extern keyword to mean 'extern or static' in that case.) It is clearly impossible to withdraw these facilities, but preparing to allow an improvement in some future standard would seem wise. I suggest adding the following after paragraph 7: Recommended practice Defining an identifier with the storage-class specifier extern when it has internal linkage is deprecated. Declaring (when not defining) an identifier with internal or external linkage and no storage-class specifier is also deprecated. An implementation shall issue a diagnostic but continue normal processing in such cases. 6.5.4 Function specifiers introduces a related and even nastier trap, which is commented on elsewhere. Public Comment Number PC-UK0103 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.3.2.1 Title: Array subscripting example Detailed description: Paragraph 2 should replace "(*(E1+(E2)))" by "(*((E1)+(E2)))", to avoid confusion. Yes, I know that the syntactic chart makes it quite unambiguous, but the current wording in paragraph 2 is very confusing. Public Comment Number PC-UK0104 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.3.6 Title: Additive operators wording Detailed description: The English in the last sentences of both paragraphs 8 and 9 (the ones beginning "Unless") is ambiguous, because the binding of "unless" and "or" in that construction is culture-dependent! I misread it several times, because the author uses a different dialect of English to the one I am most accustomed to. I suggest rewording them as follows: 8 .... The behaviour is undefined if the result is used as the operand of a unary * operator that is actually evaluated, unless either the pointer operand and the result point to elements of the same array=20 object or the pointer operand points one past the last element of an array object and the result points to an element of the same array object. 9 .... The behaviour is undefined unless both pointers point to elements of or one past the last element of the same array object. I am not entirely sure whether the first wording is needed at all, because I cannot think of a case which it excludes that is not already excluded by the previous sentence (not quoted.) Public Comment Number PC-UK0105 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 6.5.2.1 Title: Structure and union specifiers Detailed description: As I understand paragraph 15, it introduces the concept of zero-sized objects; is this deliberate? I can't see any reason why not, but it has been carefully avoided in the past. Public Comment Number PC-UK0106 Comment 1.=20 Category: Feature that should be removed Committee Draft subsection: 6.5.4 Title: Function specifiers Detailed description: Paragraph 6 is extremely confusing, and complicates an extremely tricky area of the standard still further, which is very likely to lead to the sort of implementation problems that bedevilled the implementation of linkages in early C89 compilers. The inline specifier seems to create a new sort of linkage, but is not described in those terms. Consider the following declarations with file scope: inline double joe (void) { return 0.0; } double joe (void); joe has to have external linkage because it has not been declared to have internal linkage (by 6.1.2.2), and is a definition, but is not an external definition (by this section.) So precisely what is the linkage of an inline definition? Some people believe it has no linkage, but I can find no wording anywhere in the standard that states this explicitly. Also, paragraphs 7 and 8 are misleading, and arguably incorrect as they are currently worded. In particular, "A file scope declaration with extern creates an external definition." Consider the following: static double fred (void); inline double fred (void) { return 0.0; } extern double fred (void); Unless this section can be integrated closely enough with the rest of the standard (especially 6.1.2.2 Linkages of identifiers, 6.7 External definitions and 6.7.1 Function definitions) to avoid most implementors getting confused, I suggest deleting it completely. Public Comment Number PC-UK0107 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.5.5.2 Title: Variably modified array declarators Detailed description: Forbidding the '[*]' notation at top level in function definitions isn't exactly obvious. I suggest adding a footnote after the third sentence in paragraph 3, such as: 103a. Thus * can be used only in function declarations that are not function definitions (see 6.5.5.3). Public Comment Number PC-UK0108 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 6.5.5.2 Title: Ill-definition in array declarators Detailed description: The current wording does not seem to exclude constructions like: void fred (double a[*][*], double b[sizeof(a)], double c[a[1][1]], double d[&a[1]-&a[0]]); I cannot think of any conditions where the values of such undefined calculations are critical to the behaviour of any strictly conforming program, but I think that some clarification is needed. There are two options: to define that the sizes of arrays in declarations with function prototype scope are not evaluated, and to forbid such use. I suggest the latter, adding the following: An identifier with a variable length array type of unspecified size may not be used in an expression. [ It would be possible to relax that slightly, but I can think of no good reason for doing so, and that restriction is short and sweet. ] Public Comment Number PC-UK0109 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.6.6.4 Title: Constraints on the return statement Detailed description: Paragraph 4 appears redundant, now that plain return is restricted to functions of type void. Public Comment Number PC-UK0110 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 6.6.6.4 Title: Example of the return statement Detailed description: I am utterly baffled by the example. What point is it intended to demonstrate? As it states "there is no undefined behaviour", this is a potentially serious source of confusion. Public Comment Number PC-UK0111 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 6.7.1 Title: Clarification of function definitions Detailed description: The rewriting rules in paragraph 10 have caused some confusion in C89, and will cause an increasing amount as VLAs start to be used. Consider the following: static double a[5]; void fred (double b[5]) { double (*p)[5] =3D &a; double **q =3D &b; /* This looks very odd */ p =3D &b; /* And so does this */ q =3D &a; } I suggest adding a footnote to paragraph 10, such as: 120a. This paragraph applies to compilation as well as execution; for example, the type checking will use the pointer type corresponding to any parameter specified as an array. Public Comment Number PC-UK0112 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 7.1.6 Title: Symbol providing alignment of objects Detailed description: A somewhat heated debate on the newsgroup comp.std.c brought an interesting omission in C89 to light, which interacts in extremely obscure ways of some the extensions in C9X. It is impossible to write a strictly conforming wrapper for malloc() (e.g. to store the length allocated, use count etc.) because there is no way to discover what the alignment requirement is! So I suggest adding the following to the macros: ALIGN_MAX which expands to an integer constant expression that has type size_t, the value of which is suitable for using as the alignment of any declarable type (i.e. that is a multiple of each value of alignment =20 needed by the processor). The macro shall be suitable for use in #if preprocessing directives. [ The argument for including it here (rather than ) is that it is a property of the compiled code rather than the library, and is needed by freestanding implementations that do their own space management. ] Public Comment Number PC-UK0113 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 7.4.3 Title: Ambiguity in macros for integer constants Detailed description: I am unsure how INT8_C(123456789) is supposed to be handled. Another nasty one is INT32_C(123456789123456789) in an implementation with 32-bit ints and 64-bit longs. Some clarification would be useful, especially as regards whether any diagnostics are required. I cannot suggest wording, as I am not sure what the committee intends. Public Comment Number PC-UK0114 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 7.14.7, 7.18, 7.19 Title: Ambiguity in multibyte character functions Detailed description: The wording of 7.14.7 paragraph 1 is historical, and very confusing in C9X. In particular, it implies that it may apply more generally than just this section (i.e. to 7.18 Wide character classification and mapping utilities and 7.19 Extended multibyte and wide-character utilities ). This is compounded by the fact that the latter two= =20 do not seem to define their initial shift state (except in 7.19.7.3 and 7.19.7.4). Some significant clarification of this point is needed, as any misunderstanding has fairly drastic effects. I cannot suggest wording, as I am not entirely sure what the committee intends. Public Comment Number PC-UK0115 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 7.19.4.5.7 Title: Ambiguity in the wcstok function Detailed description: I am utterly baffled by the second sentence in paragraph 3: "If s1 is a null pointer, the value pointed to by ptr shall match that stored by the previous call for the same wide string; otherwise the value pointed to by ptr is ignored." The only purpose that I can see for the ptr argument is t= o avoid wcstok needing internal storage, yet this sentence reintroduces the need for internal storage to check the value of ptr! Either I have missed something crucial, or this needs attention. Public Comment Number PC-UK0116 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 7.19.7.3, 7.19.7.4 Title: Ambiguity in restartable wide/multibyte conversion functions Detailed description: This is not entirely clear whether each function has its own internal mbstate_t object for the case when ps is a null pointer, or whether they share one. I think the former, but it should be clarified. Furthermore, it is extremely unclear whether and how the internal state can be reset to its initial state in a defined fashion, if it has become indeterminate or unknown. Public Comment Number PC-UK0117 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 6.1.2.5 Title: Major incompatibility with C89 Detailed description: Paragraph 3 introduces a fifth integer type, longer than long. The current partial draft of the rationale explains why, but conveniently ignores the major incompatibilities with C9X. There are a large number of very important, portable, conforming programs that rely on the fact that long is the longest integer type, and they will all be badly broken by this change. For example, any C89 program that needs to calculate space requirements using a mixture of size_t and off_t (with the XPG4 or Single Unix definitions) has little option but to convert both to unsigned long. This is highly portable, conforming and (as far as the actual calculations go) even strictly conforming. As this class of programs includes an immense number of commercially important applications, from sorting utilities to databases, it cannot be ignored. The best solution would be to abandon 'long long' entirely. Several vendors (such as HP) have already converted to 64-bit long on 64-bit systems, which shows that the extra type is not actually needed. If this approach is rejected, then it is imperative to prevent this change being a quiet change that will break clean, portable and conforming programs. The only solution that has been proposed is a mandatory diagnostic for any narrowing cast to either long or unsigned long. This clearly must include both explicit casts and implicit ones (e.g. when used as arguments). However, even that does not solve all of the problems. The only way for a portable or conforming C89 program to print a size_t value is to convert it to unsigned long, and print it using "%lu" or "%lx". This construction is so common that it is unreasonable to break such code without comment, and the C standard should mandate a diagnostic i at least the cases where a format string is fixed at compilation time. Frankly, I think that this is a horrible way to proceed, but I regard it as completely unreasonable for C9X to break clean, portable and conforming C89 programs without comment in the way that is being proposed. Public Comment Number PC-UK0118 Comment 1.=20 Category: Normative change to intent of existing feature Committee Draft subsection: 6.5.3, 6.5.3.1, 6.7.1 Title: Enhancements to restrict for optimisation Detailed description: I think this can be made to work, and will be of immense advantage to many people, but there are still some very serious problems to resolve. As the current proposal stands, I am afraid that the facility will be of limited use for optimisation on a good many modern machines. The four most= serious problems that I have seen are the following, and I have included suggestions to improve all of them. 1) Arrays have always been slightly second-class objects in C, though C9X makes them almost into first-class ones, but this is one area that they remain firmly second-class. For example, the term in 6.7.1 Function definitions paragraph 10 "On entry to the function" has caused some confusion in C89, but becomes extremely serious in the context of VLAs and restrict. Inter alia, it means that there is no way to declare an array parameter with bounds that can be relied on or even to guarantee that an apparently array argument is not a null pointer. The main reason this problem is so serious is that modern RISC CPUs are a hundred times as fast as their memory, and an increasing number of such architectures are introducing various forms of operand preloading to cope with this problem. To do this efficiently, a compiler needs to know both the declared size of an array and that it is v lid on function entry. This can produce much better code than if it has to delay preloading until an actual reference through the argument, and this sort of optimisation is fairly standard in Fortran. I believe that it is fairly easy to make restrict-qualified array arguments safe for optimisation (though probably not debugging). It could be done for all arguments, but there are almost certainly many programs that rely on the fact that array bounds are not checked in C. Yes, I know about the wording in sections 6.3.6 and elsewhere, but they are not watertight and hence cannot be used for optimisation. 2) There is a horrible problem introduced by 6.5.3 Type qualifiers paragraph 7, and (I am afraid) described incorrectly in 6.5.3.1 Formal definition of restrict example 3. Consider the following variation of that example: extern int * s =3D NULL; void h (int n, int * const restrict p, const int * const q, const int * const r) { int i; *s =3D 0; for (i =3D 0; i < n; ++i) *s +=3D (p[i] =3D q[i]+r[i]); } double a[5], b[5], c; s =3D &c; fred(5,a,b,b); s =3D &b[3]; fred(5,a,b,b); Unless I am much mistaken, this is conforming. It is certainly completely unoptimisable, unless the compiler can work out what the contents of s are. The following example is equally bad on many systems. extern int func(int,int); void h (int n, int * const restrict p, const int * const q, const int * const r) { int i; for (i =3D 0; i < n; ++i) p[i] =3D func(q[i],r[i]); } Firstly, these examples show that plastering arguments with const does not really help the compiler very much when it comes to optimisation, because it doesn't prevent update through any other pointer. Secondly, it shows that the restrict qualifier does very little to help with indicating that immutable arrays are actually immutable - all it does say is that a particular restrict-qualified parameter will not update another argument. There are two conditions actually needed for optimisation. One is that a m= odified object is not accessed through any other pointer, and restrict does this. The other is to know that an unmodified object is immutable during the life of the pointer, and the current specifications of restrict and const don't help much. The latter can be solved by noting that there is no need to forbid multiple accesses to restrict-qualified objects where no accesses modify the object. 3) 6.5.3.1 Formal definition of restrict paragraph 4 refers to "the array object that is determined dynamically by all references". Precisely what does this mean? Consider the following code fragment - for simplicity, assume that 'sizeof(double) > 1': void fred (restrict double a[3], restrict double b[3]) { ((char *)b)[sizeof(double)+2] =3D ((char *)a)[sizeof(double)+1]; a[0] =3D b[2]; } double array[3]; fred(array,array); Obviously, I can produce far more evil examples, including ones where the definition of the array objects depends on implementation-defined or unspecified (but not undefined) behaviour. I am afraid that a precise definition is needed. My proposal STILL does not handle cases like the following very well: void fred (restrict char *a, char *c) { double *b =3D a; ((char *)b)[5] =3D 0; *c =3D 1; } double z[10]; fred(z,&a[6]); But that is thoroughly perverse. Yes, I know that it is both legal and common, but my view is that such code is beyond hope and I don't care if it runs like a drain. The best that we can hope for is to prevent it from causing syntactic or semantic problems, which the current wording does not. 4) Consider the following: extern volatile int fred; void joe (const int * const volatile restrict a) {...} joe(&fred); Unless I have lost my marbles, that destroys the whole point of restrict. The question is whether it is worth bothering about. My view is probably not, on the grounds that C does not protect the fool from his folly, but it is debatable. It could be locked out very easily. The following are my suggestions to improve these problems. I don't guarantee that they are watertight, but they are as good as I can make them. 6.5.3 Type qualifiers. The constraint is a change from the approach taken in C89, and one that prevents several very important optimisations. So paragraph 2 should be changed to: 2 Types other than array types in function declarations or pointer types derived from object or incomplete types shall not be restrict qualified. If the combination of restrict and volatile were to be locked out, the following could be added: No type shall be both restrict and volatile qualified. The following should be added to the end of the second sentence of paragraph 7: ..., except in the case where no reference modifies any part of the object. 6.5.3.1 Formal definition of restrict We need to produce a precise definition of the object A. Also, in order to allow preloading, we need to make array bounds binding. There is some wording in 6.3.6 Additive operators paragraph 8, but I don't think that it is sufficient for this purpose. So, add after paragraph 3: The array object A determined dynamically by references though a pointer object P of type T * is defined in the following way. Firstly ignore all qualifications in T * and, if T * then becomes void *, treat P as if T * were unsigned char *. Then, consider all pointer expressions E based on P evaluated during the execution of B, convert them to unsigned char *, and denote the smallest such value by Q and the largest R. If an object is accessed, then Q and R are calculated as if each byte of the object and the byte immediately following the end of the object were addressed by separate pointer expressions of type unsigned char *. Lastly, let M and N be the largest and smallest integers, such that (unsigned char *)&P[M] <=3D (unsigned char *)Q and (unsigned char *)&P[N] >=3D (unsigned char *)R. If either M or N is not defined because one of (unsigned char *)&P[M] and (unsigned char *)&P[N]-1 would be outside the limits of the originally allocated object into which P points, the behaviour is undefined. If P is declared as a pointer parameter, A is the array with element type T and size N-M whose first element has address &P[M]. If P is declared as an incomplete array parameter and M is less than 0, the behaviour is undefined; otherwise A is the array with element type T and size N whose first element has address &P[0]. If P is declared as a a complete array parameter (whether variable modified or not) of size S and M is less than 0 or N is greater than S, the behaviour is undefined; otherwise A is the array with element type T and size S whose first element has address &P[0]. The second sentence of paragraph 4 should be changed to: Then either all references to values of A shall be through pointer xpressions based on P, or no reference to A (through expressions based on P or otherwise) shall modify any part of its contents during the execution of B. Example 3 should then become: void h (int n, int * p, const int * restrict q, const int * restrict r) { int i; for (i =3D 0; i < n; ++i) p[i] =3D q[i]+r[i]; } shows how const can be used in conjunction with restrict. The const qualifiers imply, without the need to examine the body of h, that the values of any object accessed through q and r cannot change during the execution of h. This is the precise assertion needed to optimise the loop. Note that p does not need to be restrict qualified in this example, but may allow better optimisation in a more complicated function. 6.7.1 Function definitions The other requirement for preloading is to know that an argument is not a null pointer. The following should be added after paragraph 9: 9 Upon entry to a function, if the actual argument corresponding to a restrict qualified array parameter is a null pointer, the behaviour is undefined. Public Comment Number PC-UK0119 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 5.2.4.2.2 Title: Ambiguity in specification of FLT_ROUNDS Detailed description: There is a slight ambiguity in that it is not actually stated whether FLT_ROUNDS can be set by the programmer directly (i.e. by assigning a value to it). And, as its value can be changed, this is confusing. I suggest adding to the beginning of paragraph 5 something like: FLT_ROUNDS shall expand to an expression that evaluates to the current value of the rounding mode. If FLT_ROUNDS is used in a context where a lvalue is required, the behaviour is undefined. Public Comment Number PC-UK0120 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 5.2.4.2.2 Title: Rounding in ambiguous cases without IEEE Detailed description: Paragraph 5 doesn't define precisely what the rounding mode terms mean, and there are many possible interpretations (especially of nearest rounding for numbers that fall precisely between two values.)=20 Note that this is specified by IEEE 754 but explicitly not by LIA-1. I suggest adding the following to the end of the last sentence: Unless __STD_IEC_559__ is defined (see Annex F), the exact meaning of these rounding modes is implementation-defined. Public Comment Number PC-UK0121 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 6.1.2.8.2 Title: Multiple integer representations and precision Detailed description: There is a very nasty trap here, that interacts badly with 6.2.1 Arithmetic operands and other parts of the standard. The wording does not require all integers to use the same representation which is, I suppose, reasonable. I haven't worked out all the consequences, and am not sure that I want to, but I think that the current wording is a hostage to fortune. For example: 1) What does 'precision' mean in 6.2.1.1 Characters and integers, for two types of the same size but different representations? 2) Consider the problem of converting 0x8000 between twos' complement and signed magnitude (in both directions). Frankly, I don't see how to resolve this simply, except by requiring an implementation to use the same representation for all integer data types. But that is not a trivial restriction. However, SOMETHING must be said about this problem. Public Comment Number PC-UK0122 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 6.1.2.8.2 Title: Problems with multiple zero representations etc. Detailed description: The current wording forbids the all-ones representation in ones' complement and negative zero in signed magnitude from being trap values. This compounds the original K&R mistake of assuming that integer overflow is ignored, and is slightly in conflict with the stated intention of IEEE 754. But there is a MUCH more serious problem and it is a major quiet change (as the wording stands at present). Return and initial values of zero and unspecified non-zero are defined throughout the standard, but the standard now defines two forms of zero for signed magnitude and ones' complement, which causes serious ambiguity and conflicts. For example, standard practice to test whether a set of bits is set is (value&mask)!=3D0, which will no longer work! So I suggest changing the descriptions of the sign bit to the following: - the corresponding value with sign bit zero is negated, and it is implementation-defined whether the value with sign bit one and all other bits zero is a trap value or has a value of zero; - the sign bit has value -2N, and it is implementation-defined whether he value with sign bit one and all other bits zero is a trap value or has a value of -2N; - the sign bit has value 1-2N, and it is implementation-defined whether the value with all bits one (including the sign bit) is a trap value or has a value of zero. When other sections of this standard requires a value to be initialised to zero, a function call to return zero or an expression to evaluate to zero, the implementation shall use the value consisting of all bits zero. When they require a function call to return non-zero or an expression to evaluate to non-zero, the implementation shall not use any of the values that may be trap values, whether the implementation has defined them to be trap values or not. Public Comment Number PC-UK0123 Comment 1.=20 Category: Feature that should be removed Committee Draft subsection: 6.1.3.1 Title: Hexadecimal floating-point constants Detailed description: I can see no good reason for hexadecimal ones and, yes, I do write special functions! It isn't needed for correct rounding, as there are known, acceptably efficient algorithms for doing this for other bases (and have been for 30 years and more.) Admittedly, the worst case is O(N^2) in the size of the value (exponent and all), but that case can be made extremely rare by fairly simple coding. On the other hand, it would be EXTREMELY useful to be able to specify the exact bits in a defined fashion (clearly with an implementation-defined meaning), because that would enable a program to create peculiar values (NaNs, infinities etc.) without playing unspeakable tricks with punning. The current specification is of little or no use with this. Public Comment Number PC-UK0124 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 6.2.1.3 Title: Floating to integer conversion Detailed description: Paragraph 1 is ambiguous, because there are two standard (i.e. mathematical) definitions of the fractional part of negative numbers. I suggest changing the wording to: ..., the fractional part is discarded (i.e. the number is truncated towards zero.) Public Comment Number PC-UK0125 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 6.5.8, F.7.5 Title: Initialisation to zero Detailed description: Section 6.5.8 paragraph 10 requires initialization to zero for arithmetic types, but IEEE 754 has more than one zero, and there is the problem mentioned under 6.1.2.8.2 Integer types. This is a consequence of the ambiguity in C89 over whether arithmetic objects were initialised to a value of zero or all bits zero. I don't THINK that there is any way to distinguish two null pointers in a conforming program, unless conversions of a null pointer to an integer give more than one representation of zero. I can see nothing that requires all initialisations to use the same value, though this is implied by C89 and assumed by a great many existing programs. It would be a major quiet change to allow initialisations to different, distinguishable values of zero or null pointers. I suggest adding the following to 6.5.8: If there is more than one possible representation of a null pointer or a zero for a particular type and the representations can be distinguished by a conforming program, the implementation shall use one = =20 value for all implicit initialisations of objects of that type, including subobjects of that type within unions, structures or arrays. And the following to F.7.5: 3 The value of zero used for implicit initialization shall be the positive zero. Public Comment Number PC-UK0126 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.6 Title: Which functions can raise floating-point exceptions Detailed description: The third item of paragraph 2 is not determinable by the programmer on some architectures, and will cause serious problems. Many systems use floating-point for some integer operations or handle some integer exceptions as floating-point - e.g. dividing by zero usually raises SIGFPE, and integer multiplication or division may actually be done by converting to floating-point and back again. I suggest replacing that item by: - any function call defined in the header or defined elsewhere with a floating-point parameter or result is assumed to have the potential for raising floating-point exceptions, unless the documentation promises otherwise. This requires most of the functions in to handle exceptions themselves, if they use floating-point, but that is implied by the previous wording. It has the merit of at least being determinable, which the existing wording isn't. Public Comment Number PC-UK0127 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 7.6 Title: Type of fexcept_t Detailed description: Paragraph 4 does not specify that fexcepts_t must be an integer type, but paragraph 5 describes its values in terms of integer (i.e. logical) operations. I suggest changing "represents" in paragraph 4 to "is an integer type that represents". Public Comment Number PC-UK0128 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 7.6.2 Title: Floating-point exception values Detailed description: This does not make it clear whether zero is a permitted argument. It needs clarification. I suggest changing the wording to: ... and can be zero or constructed by bitwise ORs ... Public Comment Number PC-UK0129 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.6 Title: Failure when handling exception flags Detailed description: These specifications do not allow the implementation any way to indicate failure. This is adequate for strict IEEE arithmetic, but is a hostage to fortune and prevents their use for several IEEE-like arithmetics. All such implementations can do is to not define the macros, thus implying that they cannot support the functions, whereas they may be able to support all reasonable use of the functions and merely fail in some perverse circumstances. One actual example of this is that they are often not fully resettable in signal handlers, because the return from the handler may reset them to the values they had on entry! It would be reasonable for an implementation to make these functions fail when called within such a handler, as I have done when implementing similar functions under such circumstances, but the current wording does not permit this. I think that they should all be integer-valued functions, and return an error indicator. Public Comment Number PC-UK0130 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.6.3.1 Title: fegetround and non-standard rounding modes Detailed description: What happens if the rounding mode is none of the ones defined above? I suggest adding to the end of paragraph 3: If the rounding mode does not match a rounding direction macro, an implementation-defined negative value is returned. Public Comment Number PC-UK0131 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 7.6.3.2, 7.6.4.2 Title: fesetround and feholdexcept return values Detailed description: Was it REALLY intended that non-zero indicates success and zero indicates failure? If so, these are unlike most other functions in the library. Public Comment Number PC-UK0132 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 7.6.3.2 Title: Obscure wording in fesetround Detailed description: What happens if its argument uses one form of zero where a macro expands to another form of zero (see 6.1.2.8.2 Integer types)? It uses the term "match", which is not defined elsewhere and could mean either numeric equality or representational equality. I suggest changing "does not match" to "is not equal to". Public Comment Number PC-UK0133 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.6.3.2 Title: fesetround is often unimplementable Detailed description: Many existing C implementations and even more numerical libraries have the property that they rely on the rounding mode they are called with being the one they were built for. To use a different rounding mode, the user must link with a separate library. The standard should permit an implementation to reject a change if the change is impossible, as distinct from when it does not support that mode at all. I suggest that paragraph 3 be reworded as: 3 The fsetround function returns a nonzero value if and only if the requested rounding direction has been established. It shall return zero if the direction does not match a rounding direction macro or in=20 other implementation-defined circumstances. Public Comment Number PC-UK0134 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.6.4.1, 7.6.4.3, 7.6.4.4 Title: fegetenv, fesetenv and feupdateenv are often unimplementable Detailed description: These are unimplementable on many systems without system privilege (and sometimes not even then). While most systems that have the concept of a floating-point environment allow it to be interrogated, many do not allow it to be set to an arbitrary state by unprivileged code. Note that this differs from the exception flags, which are almost invariably resettable when they exist (though even that is not guaranteed.) I suggest changing the return type from void to int in all three of these, and adding the following paragraph (with the obvious variations): Returns The fe...env function returns zero if and only the floating-point environment was successfully stored/installed. Public Comment Number PC-UK0135 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.6.4.2 Title: feholdexcept is sometimes unimplementable Detailed description: This is unimplementable on some hardware. For example, it requires the continuation after the invalid exception, when continuing after underflow is wanted, even on systems that distinguish the various levels of exception. And, yes, there are systems where continuing after underflow is possible but not after invalid - I manage one! From=20both the software engineering and implementability point of view, this needs an extra argument specifying the minimum set of exceptions to mask. I suggest making the changes: #include int feholdexcept(fenv_p *envp, int excepts); ..., and installs a non-stop (continue on exceptions) mode, if available, for a implementation-defined set of exceptions that includes all those specified in the parameter excepts. Public Comment Number PC-UK0136 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 7.7 Title: Obscure wording about constant arithmetic Detailed description: Paragraph 4 is extremely unclear. How can a constant overflow? Yes, I see what this is trying to get at, but this is not how to phrase it. I suggest the wording: ..., if available. If such a value is not available, it shall be a constraint error to use the value of the macro INFINITY as a value of type float. Public Comment Number PC-UK0137 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.7 Title: Allow infinities and NaNs for each precision Detailed description: A major flaw in paragraphs 4 and 5 is that there is no way of specifying an infinity or a NaN for double or long double, unless float supports them. While this is the common case, C9X does not require it and it is not reasonable to do so. I can see no good reason not to have three symbols for each, exactly as for HUGE_VAL. I suggest changing 'float' to 'double' in paragraph 4 and adding the following: The macros INFINITY_F INFINITY_L are respectively float and long double analogs of INFINITY. and changing 'float' to 'double' in paragraph 5 and adding the following: The macros NAN_F NAN_L are respectively float and long double analogs of NAN. Public Comment Number PC-UK0138 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.7, F.2.1, F.3 Title: Provide IEC 559 required support for signalling NaNs Detailed description: Section 7.7 paragraphs 5 and 6 are seriously incompatible with the spirit of IEEE 754, and could be regarded as being in breach of the letter of IEEE 754 section 6.2, by not providing any way to define a signalling NaN or test for whether a NaN is signalling or quiet. Furthermore, the current C9X situation does not allow a programmer to initialise his data to signalling NaNs (as recommended by IEEE 754). At the very least, there should be a macro SIGNAN for creating one and a macro FP_SIGNAN for flagging one, so I suggest adding: 4a The macro SIGNAN is defined if and only if the implementation supports signalling NaNs for the double type. It expands to a constant expression of type double representing an implementation-defined signalling NaN. The macros SIGNAN_F SIGNAN_L are respectively float and long double analogs of SIGNAN. and adding FP_SIGNAN to paragraph 6, which makes it conform with IEEE 754. This should be done even if SIGNAN is not added. Assuming that the nan function is removed (see 7.7.11.2 The nan function), F.2.1 paragraph 1 needs replacing by:: The NAN, NAN_F, NAN_L, SIGNAN, SIGNAN_F, SIGNAN_L, INFINITY, INFINITY_F and INFINITY_L macros in provide designations for IEC 559 NaNs and infinities. The only support for signalling NaNs required by this standard is that the fpclassify function (7.7.3.1) shall classify them correctly. An implementation shall define the macros SIGNAN, SIGNAN_F and SIGNAN_L only if those values are supported compatibly with IEC 559. In F.3 the last paragraph (starting "The signbit macro") should be simplified by the omission of the exclusion in brackets. Public Comment Number PC-UK0139 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: 7.7 Title: Ambiguity in specification of FP_FAST_FMA Detailed description: Paragraph 7 implies that FP_FAST_FMA should not be set if fma(x,y,z) is significantly faster than x*y+z! I suggest changing "about as fast" to "about as fast or faster". Public Comment Number PC-UK0140 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 7.7 Title: What does "supported by conversion" mean? Detailed description: Paragraph 9 is thoroughly confusing. What does "supported by conversion" actually mean? Does it mean the maximum number of digits that will be produced, a limit above which a conversion will fail or the maximum number that are guaranteed to be accurate? Paragraph 10 footnote 171 implies the last, but does not exclude either of the first two, in conjunction. And there ARE systems where printf("%.30f",1.0/3.0) produces 0.333333333333333330000000000000. I cannot suggest wording, as I do not know what the committee intends, but this facility is too vague to be useful as it stands.. Public Comment Number PC-UK0141 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.7.1 Title: Which functions can set errno Detailed description: C89 was and C9X is unclear about whether tan() and similar functions are allowed to set errno or not. Its specification has no reference to a domain error and therefore, by implication, it has no reference to errno. By 7.1.4 paragraph 3, it is therefore allowed to set errno at whim. But is this so? Furthermore, there are several implications in C9X that the handling of IEEE exception flags and errno have similar properties, so this becomes even more of a trap. I suggest adding the following wording to the end of paragraph 1: This section documents the use of errno by all the functions defined in the header , which therefore will set errno only when an error is detected (see 7.1.4). Public Comment Number PC-UK0142 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 7.7.1 Title: Extraordinary roundoff error Detailed description: I have no idea what "without extraordinary roundoff error" means. If such a term is to be included, I suggest adding the following: 1 If a function produces a range error to avoid extraordinary roundoff error, the implementation shall define the conditions when this may occur. Public Comment Number PC-UK0143 Comment 1.=20 Category: Other (conflict with IEEE 754, LIA-1 and LIA-2) Committee Draft subsection: 7.7.1 Title: and floating-point signals Detailed description: This STILL forbids an implementation from trapping bad arguments to the mathematical functions, even if the user wants such a trap. I have had dozens of users horrified when I have told them that the C standard REQUIRES implementations to produce wrong answers without a trap, and sometimes without even an error flag. It is in obvious conflict with the stated intention of IEEE 754 and LIA-1, and actually prevents an implementation from conforming to both C9X and the proposed LIA-2 simultaneously. Despite this, H.3.1.2 Paragraph 1 claims that the C standard allows "hard to ignore" trapping and diagnostics as an alternative form of notification (as required by LIA-1), but it specifically FORBIDS this in many routines of the library (e.g. ). I suggest adding the following: 4 An implementation shall provide a mechanism for programs to be executed as described above. It may also provide a mechanism by which programs are executed in a mode in which some or all domain and range errors raise signals in an implementation-defined fashion. Recommended practice If domain errors raise a signal, the signal should be SIGILL. If range errors raise a signal, the signal should be SIGFPE. It should be possible for the program to run in a mode where domain errors and range errors that correspond to overflow raise signals, but range errors that correspond to underflow do not. Alternatively, people might prefer to use SIGFPE for both classes of error; there are arguments both ways, and either choice is reasonable. If this change is not made, H.3.1.2 should be corrected. Public Comment Number PC-UK0144 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.7.3.2 Title: Serious confusion in the signbit macro Detailed description: The wording of this is seriously flawed. It says that it returns the sign of a number, but is clearly intended to test the sign bit, and these are NOT equivalent. IEEE 754 states explicitly that it does not use the sign bit of NaNs as a sign bit, and all VAX NaNs have sign bit zero (the equivalents with sign bit one are invalid numbers and not NaNs.) And there is nowhere else in C9X that requires the sign of a floating-point number to be held as a bit - surely people have not yet forgotten ones' and twos' complement floating point? I suggest replacing paragraphs 2 and 3 and footnote 175 by: 2a For valid non-zero values (including infinities but not NaNs), the signbit macro returns nonzero if and only if the sign of its argument is negative. 2b For zeroes and NaNs when __STD_IEC_559__ is defined, the signbit macro returns nonzero if and only the sign bit of the value is set. 2c For zeroes and NaNs when __STD_IEC_559__ is not defined, the signbit ma= cro returns nonzero for an implementation-defined set of values and zero otherwise. Public Comment Number PC-UK0145 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.7, 7.7.6.14 Title: Efficiency of the ilogb function Detailed description: I am distinctly unhappy with this. As a person who has written portable special function code (including things like sin/cos), I badly needed something like this to localise the system dependencies. But NOT this specification, on the grounds of severe inefficiency. There are two reasonable approaches, and C9X has fallen between them: 1) To have a composite function that returns the type of value, its sign and (only if it is finite and non-zero) its exponent and mantissa. 2) To have separate functions for each level of classification, with later ones being defined only for appropriate arguments. I suggest simply dropping the requirements to return particular values for zero, infinities and NaNs - i.e. remove the text "; it computes the value FP_ILOGB0 ... if x is a NaN", and scrapping 7.7 Mathematics paragraph 8 entirely. This could be implemented a lot more efficiently and hence would be vastly more useful. It remains compatible with LIA-1 exponentF. Public Comment Number PC-UK0146 Comment 1.=20 Category: Normative change to intent of existing feature Committee Draft subsection: 7.7.10.3 Title: The remquo function is confusing and hard to implement Detailed description: This will be extremely hard to implement on many architectures, will be a fruitful source of obscure bugs, and will baffle most users. It also creates havoc in 7.9.1 Type-generic macros. I suggest making the quo argument 'double *' and replacing the last sentence by: In the object pointed to by quo it stores the remainder as defined under the remainder function (see 7.7.10.2). If this is not done, it needs to be excluded from the list of type-generic macros in 7.9.1. Public Comment Number PC-UK0147 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.7.11.1 Title: Ambiguity in the copysign function Detailed description: What does "treat negative zero consistently" mean? Does IBM 370 arithmetic do it? Does VAX? Does Intel? Does IEEE? I suggest replacing the sentence "On implementations ... the sign of zero as positive." by Unless __STD_IEC_559__ is defined (see Annex F), it is implementation-defined whether any representations of zero are regarded as negative by this function and, if so, which. Public Comment Number PC-UK0148 Comment 1.=20 Category: Feature that should be removed Committee Draft subsection: 7.7.11.2 Title: The nan() function seems pointless and confusing Detailed description: This implies that the NaN macro takes a string argument, which is incompatible with its use in 7.7 Mathematics. Given the statement in IEEE 754 that only one NaN of each type need be provided, and the absence of facilities for handling different NaN values both in IEEE 754 and C9X, I suggest scrapping this function entirely. Public Comment Number PC-UK0149 Comment 1.=20 Category: Feature that should be removed Committee Draft subsection: 7.7.11.4 Title: nextafterx() seems pointless and confusing Detailed description: Why is this provided? Footnote 181 seems to be intended to explain, but I find it even more baffling than the function specification. It is also very unclear how it should be handled by 7.9.1 Type-generic macros paragraph 5. If this function isn't critical, I suggest scrapping it entir= ely. If this is not done, it needs to be excluded from the list of type-generic macros in 7.9.1. Public Comment Number PC-UK0150 Comment 1.=20 Category: Normative change to intent of existing feature Committee Draft subsection: 7.7.12.2, 7.7.12.3, F.9.9.2, F.9.9.3 Title: Mathematically incorrect behaviour of fmax/fmin Detailed description: 7.7.12.2 and 7.7.12.3 footnotes 182 and 183 should be scrapped. They are mathematically incorrect, as IEEE 754 uses NaNs as an error indicator and NOT a missing value indicator, and are an unreasonable restriction on non-IEEE implementations. The specification of these in F.9.9.2 and F.9.9.3 is mathematically incompatible with IEEE 754's use of NaNs. Furthermore, the example code given does not raise the invalid exception if an argument is a NaN. The combination of these provides a very serious impact on robustness. I suggest changing the wording to: 1 - If either argument is a NaN then fmax returns one of its argument NaNs; it is unspecified whether the invalid exception will be raised. The body of the fmax function might be { return (isgreaterequal(x,y) ? x : y); } 7.8.2 Complex functions =3D Comment numeric-28 =3D Public Comment Number PC-UK0151 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 7.8.2 Title: Why mention degrees versus radians? Detailed description: Why does paragraph 1 need to mention the radian versus degree problem? Because it is specified here but not in 7.7.4 Trigonometric functions, it could be interpreted as saying the former MAY be implemented using degrees! I suggest either dropping it or copying it to 7.7.4. Public Comment Number PC-UK0152 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.8.2 Title: Error handling for complex functions Detailed description: Why does C9X specifically suggest that implementations need not bother with domain and range error handling for complex functions? This makes it quite impossible to use these functions in portable code if robustness is of any importance. The argument that they may need to be implemented inline doesn't hold water, as the same applies to the real functions. Note that domain errors CAN occur for the carg function and range errors for many of them. I suggest replacing paragraph 1 by: 1 The error handling for domain errors is as specified in section 7.7.1. 2 A overflowing range error occurs if the mathematical result of the function has either or both of its real and imaginary components that cannot be represented in an object of the specified type, without =20 extraordinary roundoff error, because at least one is finite but too large. On an overflowing range error, it is implementation-defined whether the function returns an implementation-defined value for both components, or only those that cannot be represented; whether the integer expression errno acquires the value ERANGE is implementation-defined. 3 A underflowing range error occurs if the mathematical result of the function has real and imaginary components that cannot be represented in an object of the specified type, without extraordinary roundoff error, because at least one is finite but too small and the other is either finite but too small or zero. On an underflowing range error, the function returns a value of which both the real and imaginary components have magnitude no greater than the smallest positive real number in the specified type and are otherwise implementation-defined; whether the integer expression errno acquires the value ERANGE is implementation-defined. 3 An implementation may define other circumstances under which domain and range errors may occur. Recommended practice The error handling for complex functions should be as consistent with the real mathematical functions as possible, subject to the essential differences between the real and complex domains. In particular, the case where one component underflows or overflows but the other does not should be handled in a mathematically consistent fashion. Public Comment Number PC-UK0153 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 7.8.2.19 Title: carg() is undefined for a complex zero Detailed description: This is mathematically undefined for complex zeroes. I suggest adding "A domain error occurs if the argument is a complex zero." Public Comment Number PC-UK0154 Comment 1.=20 Category: Feature that should be removed Committee Draft subsection: 7.8.2.22 Title: Is the cproj function useful? Detailed description: Isn't this a little esoteric? Why not simply drop it, as it is pretty easy to provide efficiently using the other functions and macros? Public Comment Number PC-UK0155 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: Annex F Title: The status of __STD_IEC_559_COMPLEX__ Detailed description: There is a trap introduced by 7.8 Complex arithmetic, but it should be fixed here. The current specification allows an implementation to define __STD_IEC_559_COMPLEX__, but to do something completely incompatible, and STILL claim conformance because Annex G is merely informative! I suggest putting some wording in the introduction of Annex F like: An implementation that defines __STD_IEC_559_COMPLEX__ shall implement Annex G as if it were normative. Public Comment Number PC-UK0156 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: Annex F Title: Permitting diagnostics for uncleared exception flags Detailed description: One of the assumptions in the IEEE 754 model is that exception flags will eventually be either cleared or diagnosed, and this is required by LIA-1. Fortran does not specify what may be written to 'standard error', but C does, and many vendors regard the standard as forbidding them from issuing diagnostic in this case. H.3.1.1 Indicators states that C permits an implementation to do this, but provides no hint as to how. I suggest adding the following: If any of the exception flags are set on normal termination after all calls to functions registered by the atexit function have been made (see 7.14.4.3), and stderr is still open, the implementation may write some diagnostics indicating the fact to stderr. If this is NOT done, then H.3.1.1 should be corrected, or clarified to explain how such a diagnostic can be produced. Public Comment Number PC-UK0157 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: F.7.4 Title: Constant expressions and IEEE Detailed description: Hmm. I can't see any major problem with this, except that it is a bit confusing. Consider the following: static double fred[(int)7.5]; This section does NOT actually require that case to be evaluated during execution, but could it be made a bit clearer? Public Comment Number PC-UK0158 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: F.9 Title: Floating-point exception flags and errno Detailed description: Paragraph 4 is seriously incompatible with the spirit of IEEE 754 and the wording of LIA-1, and actually prevents an implementation from conforming to both C9X and the proposed LIA-2 simultaneously, for those functions that are not specifically mentioned in this annex. I suggest changing its wording to: 4 The invalid exception will be raised whenever errno is set to EDOM. Subsequent subclauses of this annex specify other circumstances when the invalid or divide-by-zero exceptions are required to be raised. There is also a possible ambiguity in paragraphs 5 and 6, and a problem caused by cases where the implementation may define extra range errors as permitted by 7.7.1 Treatment of error conditions paragraph 2 (e.g. cos(1.0e50)), that is a nasty conflict with LIA-2. It should be closed by adding the following: 6a Whenever errno is set to ERANGE, at least one of the invalid, divide-by-zero, overflow or underflow exceptions shall be raised. Public Comment Number PC-UK0159 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: F.9.1.4 Title: atan2(+-0,+-0) and IEEE Detailed description: Defining atan2(+-0,+-0) to return a finite value and not raise the invalid exception is mathematically incorrect, incompatible with robust code and the wording of LIA-1, and actually prevents an implementation from conforming to both C9X and the proposed LIA-2 simultaneously. I suggest changing these cases to do the correct thing: atan2(+-0,+-0) returns a NaN and raises the invalid exception. Public Comment Number PC-UK0160 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: F.9.3.4 Title: Inconsistent wording in frexp Detailed description: This uses the words 'returns' and 'stores' for its second argument; they should really be made consistent. Public Comment Number PC-UK0161 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: F.9.4.3 Title: pow(+-inf,+-0) or pow(NaN,+-0) and IEEE Detailed description: Defining pow(+-inf,+-0) and pow(NaN,+-0) to return a finite value and not raise the invalid exception is mathematically incorrect and incompatible with robust code. I suggest changing these cases to do the correct thing: pow(+-inf,+-0) returns a NaN and raises the invalid exception. pow(NaN,+-0) returns its NaN argument. Public Comment Number PC-UK0162 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 6.2.1.6 Title: Complex infinities and NaNs Detailed description: This is seriously incompatible with the spirit of IEEE 754 and LIA-1, in that information can be lost without flagging the fact in any way. Far worse, it REQUIRES complex infinities and NaNs to be converted to finite numbers with no indication of the fact. This is not reasonable. I suggest changing 6.2.1.6 paragraph 2 to say: 1 When a value of complex type both of whose components are finite real numbers is converted to a real type, the imaginary part of the complex value is discarded and the value of the real part is converted according to the conversion rules for the corresponding real type. When a value of complex type either of whose components is an infinity or a NaN is converted to a real type, the result is implementation-defined. And adding the following: Recommended practice If the implementation supports the concept of complex infinities, the result of converting a real infinity to a complex type should be a complex infinity and that of converting a complex infinity to a real type should be a positive infinity. If the implementation supports the concept of complex NaNs, the result of converting a real NaN to a complex type should be a complex NaN and that of converting a complex NaN to a real type should be a NaN. [ Note that conversion WITHOUT raising exceptions is provided by the creal and cimag functions, so this is not a restriction. ] Public Comment Number PC-UK0163 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: Annex G, G.3 Title: Imaginary, complex infinities, NaNs and inexact Detailed description: The concept of a complex infinity is introduced under G.4.1 Multiplicative operators, which is bizarre. It should be moved up to the top of Annex G as one main point of IEEE 654 arithmetic and the LIA standards is consistency, and specifying it this way definitely encourages (and even requires) inconsistency. So the first part of G.4.1 paragraph 4 should be moved to G.1 and the following added: A complex number with one component a NaN and the other a finite number is a complex NaN. I can't say that I like this, because a complex NaN can turn into a complex infinity, which is the converse of the rule for real numbers. I would prefer the NaN property to take priority over the infinity one. G.3.2 Real and imaginary and G.3.3 Imaginary and complex are unnecessarily repetitive and forbid any consistent handling of NaNs and infinities. I suggest replacing them both by wording that cross-references the main body of the standard, such as: G.3.2 Imaginary, real and complex When a value of imaginary type is converted to a real or complex type, it is treated as if it were its corresponding real type, converted to its corresponding complex type, multiplied by _Complex_I and converted to the result type. When a value of real or complex type is converted to an imaginary type, it is treated as if it were multiplied by _Complex_I, and converted to the result type as if that were its corresponding real type. As mentioned under 6.2.1.6, the current wording is seriously incompatible with the spirit of IEEE 754 and LIA-1, in that information can be lost without flagging the fact in any way. With IEEE 754 arithmetic, the obvious way to indicate the loss of information is the inexact exception, but most people's experience is that is raised too often to be useful. However, it should be explicitly allowed. I suggest adding the following to G.3: 1 When a complex, real or imaginary finite or infinite number is converted to one of the other two forms and the converted number does not compare equal (as if using the =3D=3D operator) to the original value, it i= s implementation-defined whether the inexact exception will be raised. 2 When a complex, real or imaginary NaN is converted to one of the other two forms and the converted number is not a NaN, it is implementation-defined whether one of the invalid or inexact exception will be raised and, if so, which. [ Note that conversion WITHOUT raising exceptions is provided by the creal and cimag functions, so this is not a restriction. ] Public Comment Number PC-UK0164 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: G.4.1 Title: Complex multiplicative operators Detailed description: Paragraph 5 sends shudders up my spine but, unfortunately, it is obvious why it has to allow spurious exceptions. However, I am 99% certain that efficient implementations are possible while raising spurious invalid, overflow and underflow exceptions only in borderline =3Dcases. But please note that I am only 99% certain! I suggest adding the following: Recommended practice A good implementation will not produce spurious invalid exceptions, except possibly when at least one of the component values is an infinity or a NaN. It will not produce spurious overflow or divide-by-zero exceptions, except possibly when abs(x)*abs(x) for at least one of its operands would overflow or be infinite or, for the second operand of the / operator only, 0.5*abs(x)*abs(x) would underflow. And, yes, I know that the example code fails to do this. However, in the light of my comments on 7.14.2.2 The srand function, it is highly desirable to have some wording that discourages implementors from taking examples as normative code. Public Comment Number PC-UK0165 Comment 1.=20 Category: Editorial change/non-normative contribution Committee Draft subsection: H.3.1, H.3.1.2 Title: Incorrect claims of LIA-1 conformance Detailed description: LIA-1 6.1.1 point (c) requires the ability to permit the programmer to specify code to compensate for exceptions if this form of exception handling is used. C does not permit such code, but H.3.1 paragraph 4 claims that it does. In particular, there is no way to return a corrected value after a numeric (SIGFPE) signal. This statement should be corrected. H.3.1.2 paragraph 4 claims that the C standard allows trap-and-terminate as well as trap-and-resume. Both of these are undefined behaviour (7.11.1.1 The signal function, paragraphs 3 and 5). While undefined behaviour is not incompatible with LIA-1 (obviously), it is seriously misleading to use it to claim that the C standard supports LIA-1 (see H.1 Introduction). This statement should be corrected. Public Comment Number PC-UK0166 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 5.1.1.3 Title: Indication of failure Detailed description: The C standard does not make any requirement on an implementation to distinguish success from failure during compilation, which causes a lot of trouble with Unix 'make' and similar utilities. It would be possible to require it to indicate failure in the cases when that is possible and it produces at least one required diagnostic. But is this a good idea? If it can be done without causing major trouble, then I think that it should be done. I have not included any text, as I am not convinced whether this is feasible (practically and politically.) Public Comment Number PC-UK0167 Comment 1.=20 Category: Normative change to intent of existing feature Committee Draft subsection: 6.5.5.2 Title: require side effects in VLA declarations to work normally Detailed description: 6.5.5.2 paragraph 3 states in part: It is unspecified whether side effects are produced when the size expression is evaluated. This rule will be extremely confusing to the normal programmer. It places a unreasonable burden, particularly if the size is determined via a function call. See the WG14 archives for a fuller discussion of the topic. Replace this sentence with: The size expression is evaluated in the normal way. For the purposes of determining the order of evaluation of subexpressions, all expressions in a declarator are evaluated simultaneously, as if they were combined by addition operators [*]. [*] Thus /int v [n++][n];/ causes undefined behavior because the expression /(n++)+(n)/ does. But /int v [n++] =3D { n++ };/ does not, because there is a sequence point between the expressions in the =20 declarator and those in the initializer. Public Comment Number PC-UK0168 Comment 1.=20 Category: Inconsistency Committee Draft subsection: 6.5.7 Title: Clarify when VLA sizes are determined NOTICE - this is a replacement for PC-UK0043, which is withdrawn. Detailed description: 6.5.7p3 reads in part: Any array size expression associated with variable length array declarators shall be evaluated with the typedef name at the beginning of its scope upon each normal entry to the block. This wording appears to say that VLA typedefs are evaluated when the block containing them is entered, even though this is not the case for any other kind of declaration (including VLAs themselves). For example:=20 { int n; n =3D 5; int v1 [n]; n +=3D 2; typedef int vec [n]; n +=3D 2; vec v2; /* ... */ } The above wording would imply that vec, and so v2, contains either 5 or an undefined number of elements, rather than 7 that the average programmer would expect. It is also worthwhile clarifying the effects of a jump to a point between the declaration and use of vec. Change the wording to: Any array size expression associated with variable length array declarators shall be evaluated with the typedef name at the beginning of its scope, and the resulting size shall be used whenever the typedef name is subsequently used. If the scope of the typedef name is entered by a jump rather than the normal sequence of execution, the associated size is unspecified. If a typedef name is used in any way while the associated size is unspecified, the behavior is undefined. Public Comment Number PC-UK0169 Comment 1.=20 Category: Feature that should be included Committee Draft subsection: 7.1.6 Title: relax restrictions on the offsetof macro Detailed description: The offsetof macro currently requires its first argument to be a structure type, and is unclear what the second argument is. There is no particular reason to forbid unions for the first argument, nor to forbid complex constructs for the second argument, provided only that the address constant requirement continues to hold. In 7.1.6 paragraph 3, change "structure" to "structure or union" in two places, and change: The /member-designator/ shall be such that given to: The /member-designator/ may be any construct, provided that given and add a footnote to the end of the paragraph: [*] Thus the member-designator may be a construct like /m [2]/ or /a.b.c/. The offset of any member of a union is 0. Public Comment Number PC-UK0170 Comment 1.=20 Category: Request for information/clarification Committee Draft subsection: 5.1.2.3 Title: Ordering of sequence points Detailed description: Paragraphs 2, 4 and 6 refer to the previous and next (or subsequent) sequence points, but a expression parse tree does not have a canonical ordering. Statements do, but they are irrelevant in this context.=20 This has caused considerable confusion with C89 in a fair number of obscure but realistic constructions, as well in perverse ones like the following: (a,++b,a)+(a,++b,a) I suggest adding a paragraph saying something like: The ordering of sequence points within an expression is only partially specified by the syntax rules and operator precedences, and an implementation may reorder expressions in any way that is compatible with those. A strictly conforming program shall not rely on any ordering of sequence points that is not required by the syntax rules and operator precedences. I believe that this is normative in the sense that it makes it clear that relying on any parse ordering is not strictly conforming, but that is probably what was always meant. Public Comment Number PC-UK0171 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 6.5.5.2 Title: Ambiguities and traps in VLAs Detailed description: Paragraph 3 says that it is unspecified whether side-effects in the sizes of VLA declarators occur. I am at a loss to understand why this exclusion is necessary or desirable, and its current wording is nothing but a trap for the programmer. In particular, it conflicts very badly with the IEEE and LIA arithmetic standards in that it explicitly permits exceptions to occur and not be flagged. Furthermore, there is no requirement that side-effects be handled consistently, even for textually identical declarators within the same function. Programmers will not expect such bizarre behaviour.=20 But perhaps the worst aspect is that it is unclear whether this lack of specification is permitted to change the actual size, as in declarers like: int m =3D 10, n =3D 3; typedef double x[(m +=3D 10, ++n, m+n)]; As the wording stands, it is unspecified whether this allocates an array of length 13, 14, 23 or 24. I am sure that this was not meant, but it is what the wording says. Worse still, consider a machine with 32-bit integers and 16-bit operations - is it allowed to update only half of an integer? This situation is a recipe for chaos, and needs resolution. I suggest one of the following solutions: 1) To define that side-effects occur as in ordinary expressions. Algol 68 and other languages have shown that this is technically simple, though existing compilers might need some reorganisation. There should be no need for incompatible changes to compiled code. After all, the compiler has to permit a function call, which can then do anything!=20 2) To make it a constraint error to use a VLA size expression that has a side-effect or calls function. This would permit almost all 'reasonable' uses, diagnose those that were invalid and give the implementor a very easy time. I doubt that most programmers would ever notice the restriction. Public Comment Number PC-UK0172 Comment 1.=20 Category: Normative change to existing feature retaining the original intent Committee Draft subsection: 6.5.7 Title: typedef and VLAs Detailed description: Paragraph 3 says that size expressions in VLAs are evaluated on entry to the block, but this is unimplementable without further restrictions. For example, consider the following: int n =3D 3; { ... int n =3D 5; double a[n]; ... } I am completely lost to know whether the declaration of 'a' gives a size of 3 or 5 or is invalid. I sincerely hope that this sentence can simply be dropped, and the size expressions in VLAs in typedefs evaluated where every programmer will expect them to be - at the place the typedef occurs. If not, considerable work is needed to say whether code like the above is allowed and, if so, what it does. Public Comment Number PC-UK0173 Comment 1 Category: Feature that should be included Committee Draft subsection: 7.14.3 Title: The alloca 'function' Detailed description: The alloca 'function' is fairly common, but was quite rightly left out of C89 on the grounds of implementation difficulty. However, the introduction of VLAs provides precisely the right mechanism to implement alloca, and this would help with porting some programs that rely on it. There are a few that need it so badly that they cannot be converted to use malloc. Furthermore, many users would like a way of allocating space on the stack and being able to trap failure in a reliable and moderately portable fashion. One of the main arguments against VLAs is that they will reduce program robustness - I don't agree, but the argument is being made. For obvious reasons, alloca cannot be required to use the same space pool as VLAs, but it is expected that most implementations will. The specification here is intended to encourage implementors to return NULL from alloca if space is not available, without making it impossible to implement if detecting that state is infeasible. Note that it is effectively always possible to raise a signal by probing the space after allocation and before return, except on systems where the 'stack' overflows into another data area and there is no global stack limit to check against. However, I have not seen a system that broken in many decades. Even on such a system, the following specification is implementable by always returning NULL. 7.14.3.5 The alloca macro Synopsis [#1] #include void *alloca(size_t size); Description [#2] The alloca macro allocates space for an object with automatic storage duration [6.1.2.4] whose size is specified by size and whose value is indeterminate and returns the address of that object. [#3] It is unspecified whether alloca is a macro or an identifier declared with external linkage. If a macro definition is suppressed in order to access an actual function, or a program defines an external identifier with the name alloca, the behavior is undefined. Returns [#4] The alloca macro returns a pointer to the allocated space if successful. An attempt to obtain more space than is available will either return a null pointer or raise one of an implementation-defined set of signals. Recommended Practice An implementation should attempt to return a NULL pointer as a failure indication if possible. If it is impossible even to raise defined signals reliably, the alloca macro should always return a null pointer. ___________end of UK comments; begining of Switzerland comments __ Date: 24 February 1998 Author: Peter Scheibli Postal Address: Swiss Association for Standardization, SNV CH-8008 Zuerich, Switzerland E-mail Address: peter.scheibli@snv.ch Comments on ISO/IEC CD 9899 (SC22N2620) Number of individual comments: 10 COMMENT #1 ----------------------------------------------------- Category: Normative change to existing feature retaining the original intent CD Subsection: 6.5.2.1 TITLE: Structs with a flexible array member are not well defined. Description: Structs with a flexible array member (the so-called "struct hack") have a number of problems. This is the first time that zero-sized objects are introduced in C, which has a surprising number of consequences not accounted for by the CD. (I communicated some of these problems to Clive D.W. Feather , who submitted similar changes to BSI in the UK. Since I do not know the outcome of this, I'll restate them here.) 6.5.2.1, =A72: Insert a new paragraph between =A72 and =A73 to define the constraints on structs with a flexible array member: "A structure with a flexible array member shall not be the type of a member of a struct or of an element of an array. The same applies to a union that contains (possibly recursively) a structure with a flexible array member. If there is a flexible array member in a structure, it must be the last member, and it must not be the only member." 6.5.2.1, =A715 Needs rewording to avoid troubles with zero-sized objects, especially the pointer-past-last-array-element rule. "As a special case, the last element of a structure may have an incomplete array type. This is called a flexible array member, and the size of the structure shall be equal to the offset of the last element of an otherwise identical structure that replaces the flexible array member with an array of one element. When an lvalue whose type is a structure with a flexible array member is used to access an object, it behaves as if that member were replaced by the longest array with the same element type that would not make the structure larger than the object being accessed. If this array would have no elements, the only legal operation is taking its address or its offset within the structure. Any attempt to access an element of such an empty flexible array member or to set a pointer past its last element results in undefined behavior." 6.5.2.1, =A717 It's not clear what "s1 and s2 behave as if" means in this context. E.g., sizeof (*s1) will most probably *not* behave "as if". Hence my reformulation: Replace "and assuming that the calls to malloc succeed, s1 and s2 behave as if they had been declared as:" by "and assuming that the calls to malloc succeed, the objects pointed to by s1 and s2 behave as if the two pointers had been declared as:" 6.5.2.1, =A718 Same correction. Replace "they then behave as if they had been declared as:" by "the objects pointed to by s1 and s2 can then be accessed as if the pointers had been declared as:" COMMENT #2 ----------------------------------------------------- Category: Normative change to existing feature retaining the original intent (Request for clarification) CD Subsection: 6.3.16 TITLE: Assignment of structs with a flexible array member considered harmfu= l. Description The current formulation does all w assignments between structures with a flexible array member, but I cannot find anything in the CD that would make the following illegal: struct X {int n; int a[];};sent void foo (struct X arg, int bar); struct X a, *b, *c; b =3D malloc (sizeof (struct X) + 6 * sizeof (int)); c =3D malloc (sizeof (struct X) + 18 * sizeof (int)); // Assume that both calls to malloc succeeded..., and // assume sizeof (int) <=3D 6. *b =3D *c; // Crash? a =3D *b; // Crash? foo (a, 42); // Crash? foo (*c, 42); // Crash? Even if the committee arrive at defining some semantics for such cases, I doubt it would be practicable, for an implementation would be forced to carry around the size of a malloc'ed block with each pointer or with the block. (That might actually be a good idea -- it might give us array bounds checking :-) I don't think it's the committee's intent. Note that assignments could be simply forbidden by defining a struct with a flexible array member as being an incomplete type, but I fear that this would again need corrections to handle (correct) cases like b->n =3D 42; // Since when can we access members of an // incomplete type? b->a[1] =3D 42; // Ditto. sizeof (struct X) // sizeof of an incomplete type? =20 Defining assignment of structures with a flexible array member as being equivalent tp a memcpy, i.e. a =3D *b; as the same as memcpy (&a, b, sizeof (struct X)); doesn't make sense either, as it would introduce a very special case in C where an assignment doesn't copy the whole object but only a part of it. I therefore propose to forbid all assignments between structures with a fle= xible array member. (Since arguments are passed "as if by assignment", parameter passing would also be covered.) 6.3.16, =A72 Replace "An assignment operator shall have a modifiable lvalue as its left operand." by "The left operand of an assignment operator shall be a modifiable lvalue whose type is neither a structure with a flexible array member nor a union containing (possibly recursively) a member whose type is such a structure." COMMENT #3 ----------------------------------------------------- Category: Normative change to existing feature retaining the original intent (Request for clarification) CD Subsection: 6.5.8 TITLE: Initialisations of structures with a flexible array member Description Subsection 6.5.8, "Initialization", does not account for structures with a flexible array member. What is supposed to happen in the following case: struct X {int n; int a[]}; struct X a =3D { 7, {1, 2, 3, 4, 5, 6, 7} }; // OK struct X b =3D { 42 }; // ?? void foo (struct X *p) { struct X copy =3D *p; // ?? // ... } The first case already is covered by the rules, but I think the second needs clarification: 6.5.8, =A721 Insert a new paragraph between =A721 and =A722: "If the initializer for a structure with a flexible array member does not specify any element for the flexible array member, that member has size zero, and the restrictions of 6.5.2.1, =A715 apply." The third one also is critical, as it is *not* covered by the proposed rule that assignments are not allowed for structs with a flexible array member. (Initialization is not defined in terms of assignment!) In fact, I think that the third case would be useful, but once again, allowing it would force implementations to carry around the size of a malloc'ed block with the block itself. To forbid the third case, 6.5.8, =A715 must be changed: 6.5.8, =A715 New wording: "The initializer for a structure that does not contain a flexible array member and that has automatic storage duration or for a union that does not contain (possibly resursively) a structure with a flexible array member and that has automatic storage duration may be a single expression t= hat has compatible structure or union type. In this case, the initial value of the object is that of the expression. All other initializers shall have the form of an initializer list as described below." COMMENT #4 ----------------------------------------------------- Category: Editorial change CD Subsection: various TITLE: Typos Description: I have only listed those typos and layout errors I wasn't sure whether they have not already been taken care of (I once published a list of such errors in comp.std.c, and got an answer from Larry Jones saying he'd noted them). 6.1.2, =A72: The second but last sentence should refer to annex I instead of annex H. 6.3.2.2, =A76: Should be rephrased. If read in isolation, one comes to the conclusion that any function declaration with a variable argument list (the ellipsis notation) results in undefined behavior, which is certainly not the intent. 6.3.2.2(6) only makes sense in connection with 6.3.2.2(5), so the visual clues to emphasize this should be improved, e.g, by inserting the text of 6.3.2.2(6) in 6.3.2.2(5) after the second sentence. 6.3.6, =A712: Correct "know" to "known" in the second line. COMMENT #5 ----------------------------------------------------- Category: Editorial change CD Subsection: 6.1.3.1, B.1.5 TITLE: Re-format the syntax Description: The syntax for hexadecimal floating point constants should be rewritten as=20 hexadecimal-floating-constant: hex-prefix hexadecimal-fractional-constant binary-exponent-part floating-suffix(opt) hex-prefix hexadecimal-digit-sequence binary-exponent-part floating-suffix(opt) hex-prefix: 0x 0X In other words, I'd factor the "0x" part out of hexadecimal-floating-constant to emphasize that there are basically only two ways to write them, not four. (Note: the current syntax also is correct, but in my opinion it's less clear.) Anyway, why not give the syntax in EBNF instead of some ad-hoc description? (I know, I know -- C89 introduced this ad-hoc notation and people got used to it, so we're stuck with it...) COMMENT #6 ----------------------------------------------------- Category: Feature to include CD Subsection: 7.15.5.8 TITLE: Reentrant version of strtok. Description: It is common knowledge that strtok() is not reentrant, which causes problems when it should be used to tokenize two strings at the same time (e.g., in nested loops.) Also, using strtok() may break independence of functionality if used in other functions -- if one uses strtok while calling still other functions, one has to know whether these other functions also use strtok() for some purpose. These well-known problems could all be resolved if we had a re-entrant version of strtok(), i.e. one that doesn't depend upon global intermediary state. Document WG14 N687 did propose such a reentrant strtok(), called strsep(). This proposal (see URL ) is reproduced below: >>>> Begin inclusion from N687: 1: Strtok cannot handle empty fields. 2: Strtok cannot handle more than a single string at a time. =20 Proposal: Provide strsep as a replacement. char * strsep(char **stringp, char *delim); The strsep() function locates, in the string referenced by *stringp, the first occurrence of any character in the string delim (or the terminating `\0' character) and replaces it with a `\0'. The location of the next character after the delimiter character (or NULL, if the end of the string was reached) is stored in *stringp. The original value of *stringp is returned. <<<< End inclusion from N687. At the danger of re-iterating old stuff (according to Peter Seebach in msg <5p5qfh$4sa$1@blackice.winternet.com> in comp.std.c, strsep() did not get sufficient support at the London meeting), I strongly urge the committee to reconsider its decision and to include strsep() as proposed in the standard. It fixes the problems strtok() has in a clean way, poses no backwards compatibility problems (its name is in a name space that was already reserved in C89), and is a very useful addition to the standard library. Note: I do not propose to *replace* strtok() by strsep(), just to *add* strsep(), thus existing C89 programs can continue to use the older strtok(). COMMENT #7 ----------------------------------------------------- Category: Normative change to existing feature retaining the original intent CD Subsection: 5.2.4.1 TITLE: UCNs and translation limits Description: 5.2.4.1, =A71 gives various minimum limits a conforming implementation must support, amongst them: - 63 significant initial characters in an internal identifier or macro name - 31 significant initial characters in an external identifier If the identifier contains universal character names, it is unclear whether a UCN counts as 1, 4, 6, 8, or even 10 characters when considering the above limits. The wording in the CD must be corrected to clarify this. COMMENT #8 ----------------------------------------------------- Category: Feature to remove CD Subsection: 6.1.8 TITLE: UCNs in preprocessing numbers Description: The syntax in 6.1.8, =A71, reads: pp-number: digit . digit pp-number digit pp-number nondigit ... and 6.1.2, =A71, defines "nondigit" as nondigit: one of universal-character-name _ a b c ... This would allow UCNs to appear in the midst of a preprocessing number. Is this intentional? I suspect not, and propose therefore that the syntax be corrected to disallow UCNs in preprocessing numbers. COMMENT #9 ----------------------------------------------------- Category: Normative change to intent of existing feature CD Subsection: 6.1.1 TITLE: "complex" should always be a keyword Description: 6.1.1, =A72 defines "complex" as a keyword only iff the header is included. Such "conditional keywords" are a particularly ugly hack. I don't quite see the rationale for this, either: backwards compatibility with C89 already is compromised by the new keywords "restrict" and "inline" and the requirement that there must be at least one type specifier in a declaration (i.e, no default to int). I therefore propose to make complex a first-class keyword that is always reserved, just like the other keywords. 6.1.1, =A72 should be adapted accordingly. COMMENT #10 ----------------------------------------------------- Category: Request for clarification CD Subsection: 6.1.1 TITLE: Imaginary types Description: The near-keyword "imaginary" is a slightly different case than "complex", as its support is not mandatory. Still, I consider the provisions made for imaginary equally ugly, and I'd be much happier if "imaginary" types could be thrown out altogether. What needs are imaginary types supposed to satisfy, anyway? Where's the prior art? I can see only a few advantages: uses less space than "complex", as no real part has to be stored, and notational convenience. However, I suspect that imaginary types are not really needed. One can use real floating types to represent them just as well, and for mixed operations with other real floating types (used for *real* values) or complex types, the appropriate conversions can be done by the programmer. If the intent was to provide some sort of type checking to guard against inadvertent use of a real floating type that (for the application's semantics) holds a coordinate on the imaginary axis as a *real" value, I must say that C never was very strong at this, despite the "typedef", and providing such strong type checking for this one special case is no good. In this case, think about a way to offer strong type checking for *all* types in general. (If I'm not mistaken, BSI will recommed that "imaginary" be not a keyword at all. As I don't know exactly what they're going to propose, [I don't quite see how one can keep imaginary types without "imaginary" being a keyword] I'm not offering my own proposition, but am just expressing my opinion that imaginary types should be thrown out.) The need for imaginary types must be critically re-evaluated. ________________________ end of SC22 N2690 ____________________________ ________________________ beginning of title page ______________________ ISO/IEC JTC 1/SC22 Programming languages, their environments and system software interfaces Secretariat: U.S.A. (ANSI) ISO/IEC JTC 1/SC22 N2693 TITLE: Contribution from Norway on Comments Accompanying the Summary of Voting on CD Approval of CD 9899 - Information technology - Programming languages - Programming Language C (Revision of ISO/IEC 9899:1990) DATE ASSIGNED: 1998-04-17 SOURCE: Secretariat, ISO/IEC JTC 1/SC22 BACKWARD POINTER: N/A DOCUMENT TYPE: SC22 Member Body Contribution PROJECT NUMBER: JTC 1.22.20.01 STATUS: WG14 is requested to consider this comment in its further deliberations on the CD. ACTION IDENTIFIER: FYI to SC22 Member Bodies ACT to WG14 DUE DATE: N/A DISTRIBUTION: Text CROSS REFERENCE: SC22 N2620, N2690 DISTRIBUTION FORM: Def Address reply to: ISO/IEC JTC 1/SC22 Secretariat William C. Rinehuls 8457 Rushing Creek Court Springfield, VA 22153 USA Telephone: +1 (703) 912-9680 Fax: +1 (703) 912-2973 email: rinehuls@access.digex.net _______________ end of title page; beginning of comment _______________ From: Magnus Y Alvestad Subject: Re: (SC22docs.478) SC22 N2690 - Summary of Voting on CD Approval of CD 9899 - C This is a mistake: | Country Positive format Negative format International format | | Italy L.1.234 -L.1.234 ITL 1.234 | Netherlands f 1.234,56 f -1.234,56 NLG 1.234,56 | Norway kr 1.234,56 kr 1.234,56- NOK 1.234,56 | Switzerland SFrs.1,234.56 SFrs.1,234.56C CHF 1,234.56 | Finland 1.234,56 mk -1.234,56 mk FIM 1.234,56 It should be: Norway kr 1.234,56 kr -1.234,56 NOK 1.234,56 -Magnus _________________ end of SC22 N2693 _____________________________________