C as a scripting language

C

CBFalconer

Richard said:
Then you murder the person who named it that. It's the only
reasonable reaction, really.

I believe there is a rarely quoted section in the C standard, which
specifies that murders so instigated must be committed with a
blunted rusty knife whose blade has various voids, and is at least
1/3 meter long. Failure to observe this restriction may result in
the application of penalties.
 
K

Keith Thompson

CBFalconer said:
I belong to a fanatical religion which specifies that one should
never fail to tuck their legs beneath their chair while typing. So
I pick up a 20 pound weight, normally used to power a grandfather
clock, hold out in front of my knees, and drop it.

LO and BEHOLD, I don't break any toes. I have followed the
standards of my religion, and the system works. It totally avoids
any trips to the hospital, doctors, etc. attributable to dropping
grandfather clock weights.

Let's assume further that dropping this 20 pound weight serves some
actual purpose.

If I tell you, without qualification, that dropping a 20 pound weight
"does not work", you can demonstrate for me that it does in fact work
for you. If I persist in saying that it "does not work", you can
reasonably tell me that I am either mistaken or lying.

If, on the other hand, I tell you that it won't *necessarily* work, or
that it's not guaranteed to work, then I'll be perfectly correct. And
you're still free to drop your 20 pound weight as long as you don't
drop it on my toes.
However, my co-worker belongs to a different religion. When he
drops that weight he fairly regularly breaks toes (his own and
others).

I claim his problem is not following the standard.

And if you had told him that "his problem is not following the
standard", you would have been on firm ground.

Leaving the metaphor and going back to reality, the code being
considered assumed that a 0 value returned by system() indicates that
the command ran successfully. There are three possible things the
standard could have said about this assumption:

A: This is guaranteed to work. If system() returns 0, the command
succeeded; if system() returns any other value, the command failed.

B: This may or may not work. system() returns an
implementation-defined result. A particular implementation might
choose to assign the meaning "success" to 0, and "failure" to other
values, or it might assign any other arbitrary set of meanings.

C: This is guaranteed not to work. An implementation on which a
successful call to system() returns 0 and an unsuccessful call
returns some other value is non-conforming.

The truth, as I'm sure we all know, is B. By saying, without
qualification, that it does not work, you are either falsely claiming
the truth of C, or carelessly failing to make the very important
distinction between B and C.
You seem to
claim that he deserves no calumny for that failure. I have no wish
to pay for his medical treatment. You seem to volunteer for that.

Nobody has said any such thing. I've seen nobody in this thread claim
that the code is anything other than non-portable. There's been some
disagreement on how important this is, and nearly universal
disagreement with the way you chose to state it.

I ordinarily wouldn't spend so much time on a dispute over wording,
but you've made this kind of claim repeatedly.
 
J

jameskuyper

CBFalconer said:
Flash Gordon wrote: ....

I belong to a fanatical religion which specifies that one should
never fail to tuck their legs beneath their chair while typing. So
I pick up a 20 pound weight, normally used to power a grandfather
clock, hold out in front of my knees, and drop it.

It would have helped your argument somewhat to choose behavior that
seems a little bit better motivated than dropping a 20 pound weight in
front of your knees. It doesn't change the validity (or lack thereof)
of your analogy - but it does remove a distracting element of the
ridiculous. The same could be said of the religious component of your
argument. However, labeling your practices as "religious" does make it
easier to fit your own behavior into an improved version of the
analogy (see below).
LO and BEHOLD, I don't break any toes. I have followed the
standards of my religion, and the system works. It totally avoids
any trips to the hospital, doctors, etc. attributable to dropping
grandfather clock weights.

However, my co-worker belongs to a different religion. When he
drops that weight he fairly regularly breaks toes (his own and
others).

A more appropriate analogy would be to consider a co-worker who uses a
digital clock that has no associated weights, and therefore no reasons
for dropping them. He therefore has, for perfectly rational reasons
that your religion prevents you from paying attention to, no need to
protect against the problem you're protecting yourself against. If he
changes jobs to a position where he does have a good reason for
dropping a grandfather clock weight in front of his feet, he will need
to change his behavior (I can't imagine what that reason could
possibly be, which is precisely how the ridiculous nature of your
chosen analogy works against you).

Of course, you're perfectly well aware of the fact that your co-
worker's behavior is safe, at least as long as he doesn't change to
working with grandfather clocks, but your religious beliefs prevent
you from truthfully acknowledging this, and forces you to lie by
saying that he's risking a broken toe.
I claim his problem is not following the standard. You seem to
claim that he deserves no calumny for that failure.

Not all code needs to be portable. Non-portable code is off-topic here
(with exceptions that are more trouble than they're worth to explain).
Bringing up such code here is inappropriate, though calumny seems a
bit harsh as a punishment for such behavior. However, that doesn't
justify lying by saying that the non-portable code won't work, not
even on the platforms for which it was intended.
... I have no wish
to pay for his medical treatment. You seem to volunteer for that.

There's no medical treatment to be paid, so long as he continues
working with digital clocks. I would object strenuously to paying for
his medical treatment if he maintains his current behavior even after
switching to a position where he does have a good reason (whatever it
might be) for dropping 20 pound weights in front of his knees.
 
J

jfbode1029

Tristan said:
Greetings.
     f = popen("ls *.c","r");
     while (fgets(buf,sizeof(buf),f)) {
         char *p = strchr(buf,'\n');
         if (p) *p=0;
         tests++;
         sprintf(cmd,"../lcc -g2 -nw %s",buf);
         p = strchr(buf,'.');
         if (p) *p=0;
         r = system(cmd);
         if (r) {
             printf("Compilation of %s.c failed\n",buf);
             CFailures[CompilationFailures++] = strdup(buf);
         } else {
             sprintf(cmd,"gcc %s.o lcclibc_asm.s -lm");
             r = system(cmd);
So what if you have a file in the directory named '&rm -rf ~&.c'?
Regards,
Tristan

This will provoke the same results as in ruby.

I explained the context (a script that starts an automatic
regression test for the lcc-win compiler) and in that
context there are no malicious files in that directory.

So how would you handle the general case, where you *don't* know if
there are malicious or otherwise badly-formed file names in the
directory? And I know the answer is equally easy in both the C and
scripting language versions for the example above, but I'm more
interested in the general case, not this specific example.

But your code does highlight one of the weaknesses of C relative to
other scripting languages; C requires more work on the part of the
programmer to handle arbitrarily sized inputs. For example, if I use
the bash "read" command like so:

read text

I don't have to make sure "text" is big enough to hold the next input
string, or to flag an error if the input is too large, or whatever.
Compare this situation to C, where I either have to size a buffer for
the biggest possible outlier (at the expense of internal fragmentation
for most inputs, not to mention "biggest possible" may change over
time), reject input that's too long for my buffer (at the expense of
failing to perform what may be a perfectly valid operation), or manage
memory dynamically (at the expense of writing code to manage that
memory).
 
C

CBFalconer

Keith said:
.... snip ...

Nobody has said any such thing. I've seen nobody in this thread
claim that the code is anything other than non-portable. There's
been some disagreement on how important this is, and nearly
universal disagreement with the way you chose to state it.

I ordinarily wouldn't spend so much time on a dispute over
wording, but you've made this kind of claim repeatedly.

Because I maintain that, on c.l.c, code should always work as
designed. I think we can all agree that, on some proportion of
systems, that code won't work. You claim that the proportion must
be 100% to warn that the code won't work. I claim that the
proportion must be 0% to claim that the code will work. And note
this applies only to c.l.c, where the topicality is controlled by
the C standard.

Also note that your requirement of 100% means that things specified
to have UB may work anywhere, because doing what was planned is one
form of UB. Thus I claim my version is more accurate. :)
 
J

James Kuyper

CBFalconer wrote:
....
Because I maintain that, on c.l.c, code should always work as
designed. I think we can all agree that, on some proportion of
systems, that code won't work. You claim that the proportion must
be 100% to warn that the code won't work.

Correct; if the percentage is less than 100%, the correct statement is
not that "it won't work", but that "it won't work on some systems".
... I claim that the
proportion must be 0% to claim that the code will work.

Correct. If the percentage is greater than 0%, then the correct
statement is not that "it will work" but that "it will work on some
systems".
Also note that your requirement of 100% means that things specified
to have UB may work anywhere, because doing what was planned is one
form of UB. Thus I claim my version is more accurate. :)

Well, program can work when they have UB. It's not a particularly
uncommon thing for programs to be non-portable by reason of UB; being
perfectly portable is actually far less common. Nor is it uncommon for
such code to work, on the platforms for which it was intended.
Therefore, your vision is a poor match to reality.
 
K

Keith Thompson

CBFalconer said:
Because I maintain that, on c.l.c, code should always work as
designed.

Well, the code in question *does* work as designed on the system for
which it's designed. (And because it doesn't work as designed on all
systems, I agree that it should have been posted elsewhere, or at
least that the non-portability should have been acknowledged.)
I think we can all agree that, on some proportion of
systems, that code won't work.

Yes. But it's not clear that it will, for the reasons we've been
discussing, fail on any system. The standard doesn't guarantee that
system() returns zero for success and non-zero for failure -- but it's
at least theoretically possible that it happens to do so on all
existing implementations. On the other hand, the code we're
discussion will certainly fail on some systems because the invoked
command does'nt exist.
You claim that the proportion must
be 100% to warn that the code won't work.
Yes.

I claim that the
proportion must be 0% to claim that the code will work.

I agree completely. I did not say that the code "will work".
And note
this applies only to c.l.c, where the topicality is controlled by
the C standard.

Which is why it's acceptable to say that a given piece of code is
off-topic -- *not* that it "will not work" when there are systems on
which it *will* work.
Also note that your requirement of 100% means that things specified
to have UB may work anywhere, because doing what was planned is one
form of UB. Thus I claim my version is more accurate. :)

More accurate than what?

You seem to be arguing against the claim that the code "will work".
Nobody made that claim, so you're arguing against a strawman of your
own invention.

"This will not work" is not the opposite of "this will work". As I
said in previous article, in text that you snipped, you are ignoring
the difference between code that will not work and code that is merely
not guaranteed to work.
 
J

jacob navia

So how would you handle the general case, where you *don't* know if
there are malicious or otherwise badly-formed file names in the
directory? And I know the answer is equally easy in both the C and
scripting language versions for the example above, but I'm more
interested in the general case, not this specific example.

lcc-win features a flexible array, and resizable strings.
Another possibility is to use ggets() from CBFalconer that also does
this.

I did not want to handle the general case because the "general" case is
not important in this setting.

In this directory there will be files of at most 10-15 characters long
that are tests for the compiler that are written there by one of us.
But your code does highlight one of the weaknesses of C relative to
other scripting languages; C requires more work on the part of the
programmer to handle arbitrarily sized inputs. For example, if I use
the bash "read" command like so:

read text

I don't have to make sure "text" is big enough to hold the next input
string, or to flag an error if the input is too large, or whatever.

C has the same capaibility if we use ggets or the lcc-win flexible
strings package.

Compare this situation to C, where I either have to size a buffer for
the biggest possible outlier (at the expense of internal fragmentation
for most inputs, not to mention "biggest possible" may change over
time), reject input that's too long for my buffer (at the expense of
failing to perform what may be a perfectly valid operation), or manage
memory dynamically (at the expense of writing code to manage that
memory).

This is plainly NOT TRUE!

As I said above there are many packages in C that do this. Besides,
one of the main thrusts of the lcc-win implementation was to provide
those higher level routines that you can use whenever you need them!

I proposed to standardize those routines in comp.std.c, and many people
near the standards committee (besides the catastrophic Gwyn) argued
that "C doesn't need this" or "anyone can do that", etc.

I am ALWAYS wong:

(1) If in a script I do not use those routines I get flamed because
there could be problems with oversize input
(2) If I propose that we standardize those routines I get flamed (by the
same people) telling that C doesn't need general routines since
anyone can write their own (the guy from siemens, not corrected by
any other committee member)
(3) If I use lcc-win's routines I get flamed because they are "non
standard" and hence non portable.

Catch 21...
 
B

Bartc

....
But your code does highlight one of the weaknesses of C relative to
other scripting languages; C requires more work on the part of the
programmer to handle arbitrarily sized inputs. For example, if I use
the bash "read" command like so:

read text

I don't have to make sure "text" is big enough to hold the next input
string, or to flag an error if the input is too large, or whatever.
Compare this situation to C, where I either have to size a buffer for
the biggest possible

The OP cut corners in his code to make sure this wasn't an issue.

Everyone knows that more dynamic, scripting-type languages are more
appropriate for this sort of task.

The main advantage of C, it's speed, is not relevant in this example and the
OP even admitted the two lots of code took about the same execution
time.

C might be feasible if you were considerably more at ease with it than any
other available language, and perhaps had your own personal C compiler
system to make the development process much more cosy and comfortable than
it might be otherwise.
 
J

jfbode1029

lcc-win features a flexible array, and resizable strings.

Awesome. What if I'm not using lcc-win?
Another possibility is to use ggets() from CBFalconer that also does
this.

Awesome. What if I don't have ggets()? What if I'm working in an
environment where IT doesn't allow me to install new libraries? What
if I'm stuck with an ancient K&R implementation on an old VAX?

You titled the thread "C as a scripting language"; forgive me for not
reading that as "C *as defined by lcc-win* as a scripting language".
I did not want to handle the general case because the "general" case is
not important in this setting.

You started this topic with the following assertion:

"...C can be used as a scripting language in the same way as, for
instance, ruby."

Apparently, what you *really* meant to say was "C can be used as a
scripting language in the same way as, for instance, ruby *as long as
you're using a specific implementation and have extremely well-behaved
data*."
In this directory there will be files of at most 10-15 characters long
that are tests for the compiler that are written there by one of us.

Which you didn't mention in your original description of the problem.
Every time you have to say, "oh, but that isn't an issue for this
specific example," you weaken your case that C can be used in the same
way as any scripting language.
C has the same capaibility if we use ggets or the lcc-win flexible
strings package.


This is plainly NOT TRUE!

As I said above there are many packages in C that do this. Besides,
one of the main thrusts of the lcc-win implementation was to provide
those higher level routines that you can use whenever you need them!

And what about those of us who are not using lcc-win? I'm asking you
to support your claim in the context of any generic C
implementation.
I proposed to standardize those routines in comp.std.c, and many people
near the standards committee (besides the catastrophic Gwyn) argued
that "C doesn't need this" or "anyone can do that", etc.

I am ALWAYS wong:

Quit being such a damned drama queen. God, you must be insufferable
to work with.
(1) If in a script I do not use those routines I get flamed because
    there could be problems with oversize input

Again, people like me are interested in how your example would work in
the *general* case, not a single case with lots of extensions specific
to a particular implementation and a bunch of assumptions that you
never mention in your original description of the problem.
(2) If I propose that we standardize those routines I get flamed (by the
    same people) telling that C doesn't need general routines since
    anyone can write their own (the guy from siemens, not corrected by
    any other committee member)

Committee members have their reasons; I don't necessarily agree with
them, but then I don't have the same perspective they do.
(3) If I use lcc-win's routines I get flamed because they are "non
     standard" and hence non portable.

Because again, not all of us are using lcc-win, so your extensions
don't really mean squat to those of us working with other
implementations.
 
J

jacob navia

Awesome. What if I'm not using lcc-win?

See the self contained version posted in a new thread.
Awesome. What if I don't have ggets()? What if I'm working in an
environment where IT doesn't allow me to install new libraries? What
if I'm stuck with an ancient K&R implementation on an old VAX?

(1) The self contained version doesn't need any extra installation
The function ggets is a dozen of lines long...
(2) You can't use ruby/perl/javascript/python/ in an old VAX either
unless you install something isn't it?
You titled the thread "C as a scripting language"; forgive me for not
reading that as "C *as defined by lcc-win* as a scripting language".

You are just displaying your bad faith. I did NOT include any
routines specific to lcc-win precisely. But even if I do not include
them i get flamed anyway!

You started this topic with the following assertion:

"...C can be used as a scripting language in the same way as, for
instance, ruby."

Apparently, what you *really* meant to say was "C can be used as a
scripting language in the same way as, for instance, ruby *as long as
you're using a specific implementation and have extremely well-behaved
data*."

No, see the new version in a new thread

[snip]
Because again, not all of us are using lcc-win, so your extensions
don't really mean squat to those of us working with other
implementations.

The fact that I did not use any lcc-win extension is just too much
work to understand?
 
J

jfbode1029

See the self contained version posted in a new thread.



(1) The self contained version doesn't need any extra installation
The function ggets is a dozen of lines long...
(2) You can't use ruby/perl/javascript/python/ in an old VAX either
unless you install something isn't it?

If it's running VMS, I would have DCL available; if it's running some
Unix variant, then I'd have at least sh or ksh.
You are just displaying your bad faith. I did NOT include any
routines specific to lcc-win precisely. But even if I do not include
them i get flamed anyway!

Because so far just about every response to any criticism of your
original code has been "that's not a problem if you use lcc-win!" You
do it in the first response quoted in this very message -- "lcc-win
features a flexible array, and resizable strings."
You started this topic with the following assertion:
"...C can be used as a scripting language in the same way as, for
instance, ruby."
Apparently, what you *really* meant to say was "C can be used as a
scripting language in the same way as, for instance, ruby *as long as
you're using a specific implementation and have extremely well-behaved
data*."

No, see the new version in a new thread

[snip]
Because again, not all of us are using lcc-win, so your extensions
don't really mean squat to those of us working with other
implementations.

The fact that I did not use any lcc-win extension is just too much
work to understand?

Then stop responding to every criticism with "that's not a problem if
you use lcc-win!"
 
C

CBFalconer

Keith said:
.... snip ...


More accurate than what?

You seem to be arguing against the claim that the code "will work".
Nobody made that claim, so you're arguing against a strawman of your
own invention.

"This will not work" is not the opposite of "this will work". As I
said in previous article, in text that you snipped, you are ignoring
the difference between code that will not work and code that is merely
not guaranteed to work.

Always bear in mind that this discussion is for and on c.l.c. As I
read your suggestions, you seem to believe that any programmer,
when handed some code to modify/use/etc., should read it in its
entirety, identify anything not guaranteed by the C standard, and
verify its action on the system in question. I maintain this is
ridiculous, not to mention time consuming. If code is not
guaranteed to work I maintain that assuming it will not work is the
safe technique, and reorganizing it so it will always work (if
possible) prevents any future problems. The first step in this
process is recognizing that the code is not guaranteed.
 
C

CBFalconer

jacob said:
.... snip ...

(3) If I use lcc-win's routines I get flamed because they are
"non standard" and hence non portable.

Not if you publish the code, which is written in Standard C. If
you use such features as some of your extensions they are not
standard, and cannot be used by others.
 
C

CBFalconer

.... snip ...


Awesome. What if I don't have ggets()? What if I'm working in an
environment where IT doesn't allow me to install new libraries?
What if I'm stuck with an ancient K&R implementation on an old VAX?

No problem. Just download:

<http://cbfalconer.home.att.net/download/ggets.zip>

written in standard C. If you need K&R you doubtless know how to
modify the source. You can install the routing wherever you wish.
It has been put in public domain, so no restrictions apply.

I am not speaking of other objections to Jacobs post. :)
 
F

Flash Gordon

Keith said:
And if you had told him that "his problem is not following the
standard", you would have been on firm ground.

Which was my original point. Especially as it was targetted at a
platform which defined this bit of implementation defined behaviour in
such a way as to make it work!

I ordinarily wouldn't spend so much time on a dispute over wording,
but you've made this kind of claim repeatedly.

Well, at least you saved me the trouble of writing a response.
 
K

Keith Thompson

CBFalconer said:
Always bear in mind that this discussion is for and on c.l.c.

Of course. Are you under the impression that I've forgotten that?
As I
read your suggestions, you seem to believe that any programmer,
when handed some code to modify/use/etc., should read it in its
entirety, identify anything not guaranteed by the C standard, and
verify its action on the system in question.

Well, that might be the appropriate course of action in some cases,
but I don't recall saying anything like that.
I maintain this is
ridiculous, not to mention time consuming. If code is not
guaranteed to work I maintain that assuming it will not work is the
safe technique,

Perhaps, but stating, without qualification, that it will not work is
simply false.
and reorganizing it so it will always work (if
possible) prevents any future problems.

Yes, but that's not always possible. In the example we're been
discussion, the program needs to read the contents of a directory;
there is no way to do that in portable standard C.
The first step in this
process is recognizing that the code is not guaranteed.

Yes, and all of us realized that quite some time ago.

Here's the problem. The posted code is not guaranteed to work by the
standard, but it does happen to work on some systems, particularly on
the system for which it was intended. Your statement that it does not
work was simply false. (A statement that it does work would have been
equally false.)

Even if you disagree with my point, do at least understand what I'm
saying?
 
C

CBFalconer

Keith said:
.... snip ...


Yes, but that's not always possible. In the example we're been
discussion, the program needs to read the contents of a directory;
there is no way to do that in portable standard C.


Yes, and all of us realized that quite some time ago.

Here's the problem. The posted code is not guaranteed to work
by the standard, but it does happen to work on some systems,
particularly on the system for which it was intended. Your
statement that it does not work was simply false. (A statement
that it does work would have been equally false.)

Even if you disagree with my point, do at least understand what
I'm saying?

I think we both understand what the other is saying. We disagree
on the attitude. For example, I would have had no problem if Jacob
had specified some routine other than system, and stated that this
was s system specific routine that returned a success/failure
status. Then the user can code accordingly, which might even be
(ignore syntax errors):

#if CSYS==abracadabra
sysproc = system
#else
sysproc = special
#endif
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top