[comp.std.c] Do non-trivial strictly conforming programs exist?

jeffrey@algor2.algorists.com (Jeffrey Kegler) (09/09/89)

One of the hopes I had for the standard was the ability to write
certain programs where portability is guaranteed.  I was hoping that
making them strictly conforming would do it.  Reading the standard has
dashed that hope.  I honestly hope the following is wrong and that
someone can point out how to write non-trivial strictly conforming
programs.

Section 2.2.4.1 says that "the implementation shall be able to
translate and execute at least one program that contains at least one
instance of every one of the following limits."  This is loosely
enough worded to allow a conforming implementation to reject almost
any program.

This apparently did not escape the Committee, whose Rationale points
out "a deficient implementation could probably contrive a program that
meets this requirement, yet still succeed in being useless."  More of
a threat than completely useless conforming implementations are a
number of seriously deficient ones, each deficient in a different
area.  Since a strictly conforming program must be portable to them
all, it must embody the lowest common denominator.  This can be low
indeed.

The Rationale expresses the hope that "ingenuity [ in contriving a
useless implementation ] would probably require more work than making
something useful."  In the real world of compiler vendors, examples of
implementations going out of their way to be defective are not hard to
find.

But let's assume the only danger is laziness and stupidity.  Take the
limit that requires one to allow "31 parameters in one macro
definition."  Space is at a premium, I want to allow a lot of macros,
and I am too lazy or stupid to do anything but reserve the maximum
space required for 31 parameters for each macro.  My implementation
can have a "oversize flag" in the macro table, putting the parameters
in a special overflow area if more than one parameter is required.
That overflow table need only have room for one macro's parameters for
the implementation to be conforming.

I will leave it as an exercise to the reader to think of even sicker
implementations which conform.

There is one group of programs I can find that are strictly
conforming.  The standard requires a strictly conforming program "not
produce output depending on any unspecified, undefined, or
implementation-defined behavior, ... ."  Any program which produces no
output may therefore take advantage of implementation-defined
behavior.
-- 

Jeffrey Kegler, Independent UNIX Consultant, Algorists, Inc.
jeffrey@algor2.ALGORISTS.COM or uunet!algor2!jeffrey
1762 Wainwright DR, Reston VA 22090

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/09/89)

In article <1989Sep8.230612.6629@algor2.algorists.com> jeffrey@algor2.UUCP (Jeffrey Kegler) writes:
>One of the hopes I had for the standard was the ability to write
>certain programs where portability is guaranteed.  I was hoping that
>making them strictly conforming would do it.

The operative term is "fighting chance".  The goal is to give programs
a fighting chance at portability.  The only way to absolutely guarantee
portability would have been to impose such a strait-jacket on conforming
implementations that the Standard would have been largely ignored by
vendors, and rightly so.

>Section 2.2.4.1 says that "the implementation shall be able to
>translate and execute at least one program that contains at least one
>instance of every one of the following limits."  This is loosely
>enough worded to allow a conforming implementation to reject almost
>any program.

The alternative would be to require acceptance of every strictly
conforming program that did not exceed any of the limits.  (We'd
probably have had to name more such limits, too.)  That would
have precluded conforming implementations in many environments,
especially on smaller systems.

>Since a strictly conforming program must be portable to them
>all, it must embody the lowest common denominator.  This can be low
>indeed.

Perfectly portable programs have always had to obey such constraints.
The Standard merely makes clear what they are.  It cannot change this
fundamental principle of the way the world happens to be.  Relatively
portable programs only fail on an insignificant fraction of actual
implementations.  All portability is relative, just as all probabilities
are conditional.

>In the real world of compiler vendors, examples of implementations
>going out of their way to be defective are not hard to find.

You must live in a different real world from mine.

>I will leave it as an exercise to the reader to think of even sicker
>implementations which conform.

This, too, has a standard X3J11 term: it's a matter of "quality of
implementation".  It is infeasible for the Standard to attempt to
force conforming implementations to be "nice" (meaning, apparently,
acceptable to Jeffrey Kegler).  The marketplace is expected to
operate to weed out seriously deficient implementations.

walter@hpclwjm.HP.COM (Walter Murray) (09/11/89)

Doug Gwyn writes:

> The alternative would be to require acceptance of every strictly
> conforming program that did not exceed any of the limits.

But doesn't the dpANS do just that, in Section 1.7?  "A conforming
hosted implementation shall accept any strictly conforming program."

With reference to the example in the basenote, a program can
be strictly conforming even though it contains TWO macro
definitions with 31 parameters in each, can't it?  

As I interpret Section 2.2.4.1, the provider of a supposedly conforming
implementation has to be able to produce a program that will be
accepted by the implementation and that contains at least one
instance of each of the translation limits.  But that doesn't
excuse the implementation from accepting a program which contains
more than one such instance, does it?

Walter Murray
--

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/12/89)

In article <12570025@hpclwjm.HP.COM> walter@hpclwjm.HP.COM (Walter Murray) writes:
>But doesn't the dpANS do just that, in Section 1.7?  "A conforming
>hosted implementation shall accept any strictly conforming program."
>As I interpret Section 2.2.4.1, the provider of a supposedly conforming
>implementation has to be able to produce a program that will be
>accepted by the implementation and that contains at least one
>instance of each of the translation limits.  But that doesn't
>excuse the implementation from accepting a program which contains
>more than one such instance, does it?

Hmm, this is trickier than I thought.  The only way that the first
sentence of 2.2.4.1 seems to make sense, in view of what you cited
from 1.7, would be that ALL strictly conforming programs must be
ACCEPTED, but only ONE particular program is required to be TRANSLATED
and EXECUTED.  I'd been thinking that "acceptance" by a language
translator somehow implied translation and executability or the result,
but no I wonder what IS meant.  Dave, help!!

jeffrey@algor2.algorists.com (Jeffrey Kegler) (09/12/89)

In article <12570025@hpclwjm.HP.COM> walter@hpclwjm.HP.COM (Walter Murray) writes:
>Doug Gwyn writes:
>
>> The alternative would be to require acceptance of every strictly
>> conforming program that did not exceed any of the limits.
>
>But doesn't the dpANS do just that, in Section 1.7?  "A conforming
>hosted implementation shall accept any strictly conforming program."

I think we have an outright error in the standard.  I can only read
what the thing says, but I guess the intentions were that 1.7 in the
standard be more loosely worded.  The wording of 1.7 does contradict the
intention as hinted at in the footnote and explicitly stated in the
Rationale.

The only way to make the standard internally consistent on this point,
as it sits, is to read it as defining strictly conforming programs out
of existence.

>With reference to the example in the basenote, a program can
>be strictly conforming even though it contains TWO macro
>definitions with 31 parameters in each, can't it?  

No.  The implementation need execute only ONE program containing ONE
instance of a 31 parameter macro.  (2.2.4.1) The Rationale points out
this was explicitly the intent.  Confronted with the choice of trying
to prevent perverse implementations and of trying to allow ANSI C to
be ported to the most restrictive of environments, X3J11 went all the
way over to the second, knowingly and as the result of carefully
deliberated choice.  Conforming implementations can get very perverse
indeed as a result.

A conforming implementation can: 1) impose special requirements on the
"oversize" macro, such as its name, location, etc., 2) do the same
thing with function calls with more than one argument, 3) restrict all
lines except one to 32 characters (a tempting choice for
implementation on screens of 40 character width), 4) allow only one
nested parenthesized expression for declarators and one more for full
expressions, 5) as the Rationale says, make itself totally unusable in
the above ways and a bunch of other ways.

I stared at 2.2.4.1 for weeks before I allowed myself to believe it
means what it says, neither more nor less.  Then I realized the Void.
It was all very Zen.

> But that doesn't excuse the implementation from accepting a program
> which contains more than one such instance, does it?

Absolutely, explicitly and intentionally.
-- 

Jeffrey Kegler, Independent UNIX Consultant, Algorists, Inc.
jeffrey@algor2.ALGORISTS.COM or uunet!algor2!jeffrey
1762 Wainwright DR, Reston VA 22090

jeffrey@algor2.algorists.com (Jeffrey Kegler) (09/13/89)

In article <11037@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>In article <12570025@hpclwjm.HP.COM> walter@hpclwjm.HP.COM (Walter Murray) writes:
>>But doesn't the dpANS do just that, in Section 1.7?  "A conforming
>>hosted implementation shall accept any strictly conforming program."
>
>Hmm, this is trickier than I thought.  The only way that the first
>sentence of 2.2.4.1 seems to make sense, in view of what you cited
>from 1.7, would be that ALL strictly conforming programs must be
>ACCEPTED, but only ONE particular program is required to be TRANSLATED
>and EXECUTED.  I'd been thinking that "acceptance" by a language
>translator somehow implied translation and executability or the result,
>but no I wonder what IS meant.  Dave, help!!

The term "accept" has no definition I can find in the standard.  I
hope we do not resolve this by deciding to define "accept" in a way
that an implementation can "accept" a program it does not translate
and execute.  Essentially you would be saying any sentence which
contains the word "accept" was inserted into the standard to occupy
space.  One such sentence is the one which defines conforming
programs.

To eliminate the definition of conforming program in order to save the
definition of strictly conforming would seem counter-productive.

The most reasonable solution that is in accord with the intent of
X3J11 as expressed in the Rationale, is to "accept" that 1.7 has a
"bug" in it, and was not intended to mean what it clearly says.
Looser wording here could make "maximally portable" and "strictly
conforming" synonymous.

This is not my preferred solution (that would be to tighten up
2.2.4.1) -- in fact it eliminates the (currently quite good)
possibility of reading it into the standard.  But it seems too late in
the game to change the intent of the committee.  A standard making a
true test suite (one which compiles and executes on all conforming
implementations) possible, and providing a standard of portability
that gives it more than "a fighting chance" (Rationale 1.7) seems not
to be in our stars.
-- 

Jeffrey Kegler, Independent UNIX Consultant, Algorists, Inc.
jeffrey@algor2.ALGORISTS.COM or uunet!algor2!jeffrey
1762 Wainwright DR, Reston VA 22090

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/13/89)

In article <1989Sep12.164622.18909@algor2.algorists.com> jeffrey@algor2.UUCP (Jeffrey Kegler) writes:
>In article <12570025@hpclwjm.HP.COM> walter@hpclwjm.HP.COM (Walter Murray) writes:
>>With reference to the example in the basenote, a program can
>>be strictly conforming even though it contains TWO macro
>>definitions with 31 parameters in each, can't it?  
>No.  The implementation need execute only ONE program containing ONE
>instance of a 31 parameter macro.

Walter was correct.  The implementation is obliged to provide a
single example that it handles correctly and that stresses all the
minimum limits.  That definitely was the intent of the committee
as I recall the discussion at X3J11 meetings.  The constraints on
strict program conformance are different; as I recall the intent,
strict program conformance was supposed to mean that the program
does not violate any constraint of the standard and does not rely
on any behavior flagged as explicitly "implementation-dependent"
(using these terms in their loose English meanings here).  There
was not supposed to be any guaranteed that a strictly-conforming
program work properly on all conforming implementations, unlike
what 1.7 seems to be trying to guarantee.  It merely would have
the best chance that the Standard could provide of doing so.

>A conforming implementation can: ... as the Rationale says, make
>itself totally unusable in the above ways and a bunch of other ways.

Certainly it COULD be a useless piece of shit.  In which case,
the expectation is that it would not do well in the marketplace.
There are far too many C implementations for ones that exhibit
continued, severe deficiencies to survive.  The "Standard"
imprimatur is not intended to be a warranty of merchantability
or fitness for any particular purpose.  It merely lets you know
that you have the RIGHT TO EXPECT your carefully-coded portable
program to compile and execute with minimum hassle in such an
environment.  That's significantly better than the previous
state of the art.

>> But that doesn't excuse the implementation from accepting a program
>> which contains more than one such instance, does it?
>Absolutely, explicitly and intentionally.

Only "legally" (in the loose sense).  Morally, absolutely not!

rtm@grenada.UUCP (Richard Minner) (09/16/89)

 
In some article or other Jeffrey Kegler writes, among other things:

|                           ... Confronted with the choice of trying
| to prevent perverse implementations and of trying to allow ANSI C to
| be ported to the most restrictive of environments, X3J11 went all the
| way over to the second, knowingly and as the result of carefully
| deliberated choice.  Conforming implementations can get very perverse
| indeed as a result.

OK, this makes sense, adding as Doug Gwyn and others have that
one hopes the "marketplace" will weed out any such perverse
implementations.  (Still, I do so pity the poor soles working for
some large bureaucracy who have some truly perverse
implementation specified for them.  Stranger things have
happened.)  What's not clear is why X3J11 couldn't have tightened
up 2.2.4.1 without adversely affecting the standard's chances in
"the most restrictive of environments."  For example could not
2.2.4.1 be worded something like (not exactly, mind you):

    2.2.4.1  Translation limits

	     In so far as the implementation has sufficient
	storage available, it shall be able to translate and
	execute any otherwise conforming program that does not
	exceed any of the following limits: 

	o    (bunches of limits, reworded ever so slightly)

Since this would imply such things as accepting a program with
1024 macros with 31 parameters each, you could to add a limit:

	o    2048 (4096? 1024?) total macro parameters.

Plus any other newly implied totals that may need to be limited,
and maybe distinguish between macros with and without parameters
and so forth.

In other words, it hardly seems fair to expect an implementation
to perform miracles (such as creating memory out of thin air) but
we might reasonably expect it to spread what it has at least
somewhat evenly (more of the "fighting chance" ethic).  I believe
that the above approach would do away with "just one instance of
each limit" perversities without imposing any other restrictions.

Here are just a few guesses as to why 2.2.4.1 is as it is:

1. My concept of "most restrictive of environments" is flawed.
   There are other considerations besides storage capacity
   and the current 2.2.4.1 addresses them as best as possible.

2. One such "restriction" might be that in some environments
   there may be minimal resources (money) available for
   ANSI C compliance.  If such an environment currently
   uses fixed size tables and such, gluing on the current
   2.2.4.1 requirement will be significantly cheaper (if
   pointless) than complying with my suggested 2.4.4.1.
   (I hope this isn't it.)

3. For horridly complex reasons that no one wants to discuss
   any more because it really is late and we want to go home.

If 3, someone just say so and I'll go away.  Otherwise I'd
appreciate any comments.

Thanks to all for a very interesting discussion so far.
And Doug, who's Dave?  Why hasn't he helped yet?




-- 
Richard Minner  || {uunet,sun,well}!island!rtm     (916) 447-7081 ||
                || Island Graphics Corporation     Sacramento, CA ||

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/17/89)

In article <425@grenada.UUCP> rtm@grenada.UUCP (Richard Minner) writes:
>And Doug, who's Dave?  Why hasn't he helped yet?

Dave Prosser was the Redactor (editor of the draft Standard).
He may be on vacation, or perhaps doesn't feel like responding.
That's his prerogative.

jeffrey@algor2.algorists.com (Jeffrey Kegler) (09/17/89)

In article <425@grenada.UUCP> rtm@grenada.UUCP (Richard Minner) writes:

>For example could not 2.2.4.1 be worded something like (not exactly,
>mind you):
>
>    2.2.4.1  Translation limits
>
>	     In so far as the implementation has sufficient
>	storage available, it shall be able to translate and
>	execute any otherwise conforming program that does not
>	exceed any of the following limits: 
>
>	o    (bunches of limits, reworded ever so slightly)
>

I would rather leave the present wording.  At least it comes straight
out and says "Jeffrey, if you want 100% portability of anything you
can just forget it.  Take a hike.  Go pound sand.  Forget it."  The
above says the same thing in a more equivocal way.  It would set me
looking through the standard (in vain) for definitions of
"sufficient", "storage", and "available".  I would a lot rather see
the standard explicitly refuse to give me what I want, than
equivocate.  With the explicit language, we all know what to expect.

One thing X3J11 did well is realize that writing a standard is more
like programming than writing English.  You have to assume you are
writing for a perversely logical audience.  If I was doing a
implementation, it was already done the wrong way, and a deadline on
which a lot of market share could hang was at stake, the only way I
could get them to change is quote chapter and verse and say, "thus
X3J11 sayeth".  Unless I could tell them "we will lose on proposals
because the competition will *prove* ours is not an ANSI C compiler,
as required in the RFP".  X3J11 took care of the pleas to implementors
to behave in the footnote and the Rationale, which is where such
things belong, if anywhere.

I do not think at this late date an attempt to amend a decision
deliberately made by X3J11 will succeed.  If I could (I believe it
is much too late) I would change 2.2.4.1 to a series of things like

    A conforming implementation must translate and execute any
    otherwise strictly conforming translation unit which contains no
    more than 1024 macro identifier definitions, provided that they
    are all declared with no more than 31 parameters and never invoked
    with more than 31 arguments.

In the above, if your program contains 1024 macros and does not
compile, the implementation loses.  If it contains 1025 and does not
compile, you lose.  One macro with 32 parameters, you lose.
-- 

Jeffrey Kegler, Independent UNIX Consultant, Algorists, Inc.
jeffrey@algor2.ALGORISTS.COM or uunet!algor2!jeffrey
1762 Wainwright DR, Reston VA 22090

walter@hpclwjm.HP.COM (Walter Murray) (09/18/89)

Richard Minner suggested:

> Could not 2.2.4.1 be worded something like (not exactly, mind you):

>     2.2.4.1  Translation limits

> 	     In so far as the implementation has sufficient
> 	storage available, it shall be able to translate and
> 	execute any otherwise conforming program that does not
> 	exceed any of the following limits: 

A relevant passage might be this from Section 1.2, which is hard for me to
reconcile with the requirement in 1.7 about a conforming implementation
"accepting" any strictly conforming program:

   "This Standard does not specify ... the size or complexity of a
   program and its data that will exceed the capacity of any
   specific data-processing system or the capacity of a particular
   processor."

One could argue from this that, as long as it can translate one
particular program as described by 2.2.4.1, a conforming implementation
is free to reject any other program as being too "complex".

Walter
------

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/20/89)

In article <12570026@hpclwjm.HP.COM> walter@hpclwjm.HP.COM (Walter Murray) writes:
-A relevant passage might be this from Section 1.2, which is hard for me to
-reconcile with the requirement in 1.7 ...
-One could argue from this that, as long as it can translate one
-particular program as described by 2.2.4.1, a conforming implementation
-is free to reject any other program as being too "complex".

I agree that it's hard to reconcile 1.2 with 1.7.  I think 1.7 makes
too definite a statement and that 1.2 and 2.2.4.1 more properly
indicate what was intended.