Has thought been given given to a cleaned up C? Possibly called C+.

  • Thread starter Casey Hawthorne
  • Start date
D

Dag-Erling Smørgrav

Richard Delorme said:
#interface "square"

The instruction meaning the compiler is going to look for the
interface in the file libsquare.a or square.dll or whatever depending
on the implementation.

Riiight.

That's a non-starter.

DES
 
R

Richard Bos

Willem said:
Keith Thompson wrote:
) Currently, I can have a file "square.c" that defines a number
) of functions, and another file "square.h" that provides visible
) declarations for *some* of them. Given your #interface proposal,
) how do I specify that some functions in "square.c" are intended to
) be used by client code, and some are internal?

Err... You could use the 'static' keyword ?

If you wanted a function that is internal to that file only, yes. I have
also written libraries which had certain internal functions - internal
_to the library_, that is - which were declared in one set of header
files, for use by the library code itself, but not in the public
headers.

Richard
 
B

Ben Bacarisse

bartc said:
Yes, I had to use this code:

void setbinaryconsole(void) {
_setmode(_fileno(stdout),_O_BINARY);
}


Only that text mode had a lower profile. It seems to be the default
mode on fopen(), and the default mode (with obscure, awkward, and
not-easily-portable overrides) on stdout.

It seems reasonable to me that it be the default for stdout and
stderr. In decades of using C, I don't recall wanting anything other
this default behaviour. When this topic comes up again (and I am sure
it will) it would help if you realised that, whatever it is, you have
something of a special case.

I agree that it is hard to change for stdout, and if you limit you
objection to that point I promise to keep out of the debate. :)

BTW there is a "standard" way to do this:

freopen(NULL, "wb", stdout)

but, sadly, I don't think this is supported by all C libraries. In
some sense your objection is a QOI issue, but a valid one.
If text mode was also to convert tabs to spaces and vice versa, you'd
know how I feel about it messing with newlines.

No, that would be absurd and I don't think the current situation is
absurd. However, I do know how you feel -- I can tell that from what
you write. You have what is, in my experience, an unusual requirement
(I am tempted to ask how it comes about, but I suspect that it too
huge a discussion for me) and I don't think that merits deriding what
many people have found to be an acceptable (albeit flawed) solution.
 
K

Keith Thompson

bartc said:
It was quite a literal string. And someone might anyway want to output
binary codes using printf(), why not? Perhaps there is a problem with
using an actual file. Perhaps the stdout output is to be piped to
another program which does some more processing. There's any number of
reasons why a binary stdout is useful.

If the output doesn't have to go to stdout, you can use fprintf on
a text or binary stream -- just as you can use fwrite() on text or
binary stream.
Yes, I had to use this code:

void setbinaryconsole(void) {
_setmode(_fileno(stdout),_O_BINARY);
}

freopen(NULL, "wb", stdout);

I just tried this on Linux, and it didn't report any errors, but of
course there was no effect on the output. I'll try it on Windows
later today. It might not work on some systems, but it's the first
thing I'd try before resorting to system-specific code.
Only that text mode had a lower profile. It seems to be the default
mode on fopen(), and the default mode (with obscure, awkward, and
not-easily-portable overrides) on stdout.

There is no default mode for fopen(); you have to specify the mode
as a string ("r", "w", "a", "rb", "wb", "ab", etc.) on each call.
I suppose the fact that it's "w" rather than "wt" for text mode
could be taken to imply that text mode is the default, but I hardly
think that's much of a problem.

Making binary the default mode for stdout would be far worse.
If text mode was also to convert tabs to spaces and vice versa, you'd
know how I feel about it messing with newlines.

LF, CR, and CRLF aren't the only end-of-line representations.
The C standard library doesn't have the luxury of limiting itself
to systems with simple text file formats. And if you need to work
around C's solution to the problem, it's not that difficult.
 
R

Richard Delorme

Le 18/03/2010 00:18, Alan Curry a écrit :
| - In the source file, use a new instruction that indicates where to
|find the function type. For example:
|
|#interface "square.c"
|
|int main()
|{
| /*... code using the function square... */
|}
|
|So #interface will open the square.c file and decipher the function type
|from its definition.

So I have to keep a permanent local copy of the full source code of every
library I want to compile against? Currently I only need the header files and
compiled lib*.(a|so) and as someone who doesn't buy a new hard drive every 6
months, I like it that way.

There are even some libraries that are deliberately distributed without
source code, so the users only have the header files and object code to work
with. Those people won't like your idea either.

What is done from a source code file could be done from a library. See
my answer to Dag-Erling Smørgrav.
 
K

Keith Thompson

Keith Thompson said:
freopen(NULL, "wb", stdout);

I just tried this on Linux, and it didn't report any errors, but of
course there was no effect on the output. I'll try it on Windows
later today. It might not work on some systems, but it's the first
thing I'd try before resorting to system-specific code.
[...]

Using one Windows compiler, freopen() returned NULL and set errno to 2
("No such file or directory"). Oh, well.

Still, it looks like you have a solution for your (rather unusual)
problem, even if it's not terribly clean.

Incidentally, I suggest that the name "setbinaryconsole" is unclear;
stdout doesn't necessary go to a console.
 
P

Phil Carmody

Jasen Betts said:
if you have't got strlcpy you can use sprintf with a length...

#define alt_strncpy(d,s,l) if(l)sprintf(d,"%.*s",l-1,s)

not without protection -

void select(int w, int l, char*d, char const*s1, char const*s2)
{
if(w)
alt_strncpy(d,s1,l);
else
alt_strncpy(d,s2,l);
}

do { ... } while(0) it.

Phil
 
R

Richard Bos

Dr Malcolm McLean said:
Exponentiation is the obvious basic operation that lacks an operator.
The convention is Chinese hat.

No, the convention _in BASIC_ is the circumflex. Actually, the original
convention in BASIC was up-arrow, but ASCII changed that code point to
circumflex. The convention for the use of the circumflex varies largely
between languages. For example, in Pascal it means neither xor nor
exponentiation, but pointer; in REXX, it means logical not. The
convention for exponentiation also varies; in Fortran and REXX it is **,
while many languages have no operator for it, just as C.
Unfortunately that has been used for XOR. So two Chinese hats. However
that looks too much like logical XOR.

There is no reason to have a logical xor operator. Logical and and not
are useful to have seperately from bitwise and and not mainly because
they short-circuit. However, logical xor cannot short-circuit: you
always have to evaluate both operands. The killer blow for a logical xor
is, though, that we already have one for true boolean values: !=.
Therefore, _if_ we want to add an exponentiation operator to C (and on
that point I myself am more or less apathetic), the obvious choice is
indeed ^^.

Richard
 
R

Richard Bos

Eric Sosman said:
[...]
If there was an operator keyword (or something) that would declare
a one-or-two parameter function to take its arguments in that style,
there would be no need for extra keywords.

Then you could have

a = b pow c;

"Hello, world!\n" fputs stdout;

know you dup it get want where to if Forth.

Richard
 
R

Richard Bos

Andrew Poelstra said:
I'm not sure that the compiler is the biggest concern here. More
to help out the people reading the code, who might see

a * b + c * a

and think, oh, I can simplify that:

a * (b + c)

And move on, believing the code to be shorter and therefore easier
to comprehend, unaware that a, b, and c were all matrices and he
just caused an operator failure (which would mean...?) or possibly
a subtle and well-hidden bug if (a * b) ~= (b * a).

And just to answer the obvious objection: yes, there _are_ exotic number
systems, not just matrices, where multiplication is not associative with
addition.

Richard
 
R

Richard Bos

Eric Sosman said:
On 3/10/2010 9:14 AM, bartc wrote:

(Shrug.) I find it easier to read a more compact notation.
Quickly, now: is the 4096's bit set or clear in

2x11011110101011011011111011101111

? If the number were written as 0xDEADBEEF would you reach your
answer more or less rapidly?

I have no idea if asked to be quick, and even less rapidly,
respectively.
However, if given a mouse pointer or bitmask, I find it much easier to
tell what it looks like if it's in binary than if it's in hexadecimal.
C has a lot of types. You dislike this? Rather just get
along with unaided `int', perhaps?

Only as long as it's 64 bits large, of course.

Richard
 
D

Dag-Erling Smørgrav

Richard Delorme said:
What is done from a source code file could be done from a library.
See my answer to Dag-Erling Smørgrav.

No, no, no, no and no. It would be a paradigm shift for C compilers.

Currently, a C compiler works more or less as follows:

1. The preprocessor expands macros, resolves conditionals and removes
comments.

2. The parser parses the output from the preprocessor and produces some
sort of intermediate representation.

3. The optimizer manipulates the intermediate representation to produce
more effective and / or smaller code.

4. The code generator translates the intermediate representation to
assembler code.

5. The assembler translates the assembler code to machine code and
produces a binary object that contains code, initialized data, and
information about symbols that are present in the object or that the
object references.

6. The linker combines the binary object(s) with various libraries and
produces an executable or a library.

No stage in this process has any knowledge about any other stage beyond
a simple understanding of what sort of output the previous stage
produces and what sort of input the next one expects, and sometimes not
even that (the optimizer, for instance, is invisible to the parser and
the code generator). Many toolchains implement step 1, steps 2 - 4,
step 5 and step 6 as four different, interchangeable programs which can
run independently of each other. Some also separate step 2 from steps 3
and 4.

What you propose turns everything upside-down. While the parser can
easily include the necessary information in its output, it has no way of
retrieving that information, unless you teach it everything that the
linker knows, and then some... it gets even worse for cross-compilers,
because the object format for the target might be completely different
from that used on the host. The target might not even *have* an object
format - on many embedded platforms, the linker outputs a memory image
which is written directly to the target's SRAM.

And what about preprocessor macros defined in library headers? They are
needed at the preprocessing stage, but the preprocessor doesn't even
know that what it's looking at is C (or C++ or ObjC or whatever, since
most implementations use a single preprocessor for all languages they
support), so how will it know where to look for them?

DES
 
R

Richard Bos

jacob navia said:
Richard Bos a =E9crit :

The container library is around 80K (32 bit machines)

Don't be daft. You know damned well that mere code size is no measure of
complexity, let alone of specification size.
You have remained silent (as all other "regs") in the discussions
about the library here.

No, I haven't. I have always said, and will continue to say, that I am
not going to consider the internal details, simply because the idea is
wrong from the start.

Richard
 
R

Richard Bos

Andrew Poelstra said:
Feeling C++-ey would be simple enough without any standard library
changes:

namespace std {
#include <stdio.h>
#include <stdlib.h>
}

And boom, you've got std::malloc() and std::puts() and all that.

Barf bucket, please.

Richard
 
R

Richard Bos

Jonathan Leffler said:
The proposed extra functions are currently in TR24731-1.

Argh, argh, argh. I quote:

# 6.5.4.1 The gets_s function
# Synopsis
# 1 #define _ _STDC_WANT_LIB_EXT1_ _ 1
# #include <stdio.h>
# char *gets_s(char *s, rsize_t n);
# Runtime-constraints
#.....
# Recommended practice
#.....
# Consider using fgets (along with any needed processing based on
# new-line characters) instead of gets_s.

After that, need I even explain any more what is bletcherously idiotic
about this whole idea?
They are not all identical to the Microsoft functions of the same name.

I don't even know whether that's worse or better.

Sad is not the word to describe it.

Richard
 
R

Richard Bos

James Kuyper said:
I think his point is that ANY function can be misused, by giving it the
wrong arguments, or by writing code around the function call that is
based upon a mistaken concept of how it works, or by using it when you
actually should be using some other function, and that strncpy() has
nothing wrong with it that doesn't fall into one of those categories.

That's true as far as it goes, but it has to be said that strncpy()
makes this easier than fgets(), simply because it does something
different than what a logical interpretation of the name (and comparison
with the completely reasonable strncat()) would lead one to believe. If
it were called strpad(), it wouldn't be abused nearly as much.

Richard
 
F

Flash Gordon

Richard said:
Argh, argh, argh. I quote:

# 6.5.4.1 The gets_s function

# Recommended practice
#.....
# Consider using fgets (along with any needed processing based on
# new-line characters) instead of gets_s.

After that, need I even explain any more what is bletcherously idiotic
about this whole idea?

A "security" library proposal that include function that it recommends
you don't use? Seems plain stupid to me.
I don't even know whether that's worse or better.

<snip>

Maybe they've improved a few, and on the next version they will improve
a few more (or remove the ones needing removal)?
 
R

Rod Pemberton

Keith Thompson said:
Rod Pemberton said:
[in response to Keith question]

#include <stdio.h>
#include <stdlib.h>

#define HW "Hello World!\n"

int main(void)
{
FILE *out;
char ch;

out=tmpfile(); /* ANSI wb+ */
fprintf(out,HW);
rewind(out);
while(1)
{
ch=getc(out);
if(feof(out))
break;
putchar(ch);
} /* because I could... */

exit(EXIT_SUCCESS);
}

So you print "Hello World!\n" to a binary file, then you read it back
and print each character *to a text stream". The whole rigmarole
of writing the string to a binary stream and reading it back again
accomplished, at best, exactly nothing (assuming that the binary file
isn't padded with additional null characters, which is permitted).

Exactly...

Strictly speaking, you've written a "hello world" program that
uses binary mode -- but it doesn't use binary mode to produce the
"hello world" output.

Well, you made no specification that the primary output must be made to the
console. The only specification was to use binary mode, which I did. As
far as you specified, I could've fprintf()'d "Hello World!\n" to a file and
let the user figure out how to display it.

Recall lack of specificity:

KT> You can't even write a portable "hello world" program
KT> using binary mode.
Do you have something that actually supports your claim? Can you
write a portable "hello world" program that doesn't use text mode?

Well, that wasn't my claim. It was yours. I made no claims about
_portable_ programs _without_ text mode, or even "hello world" programs for
that matter. I said _binary_ was _well_suited_ for _text_. And, it is. It
usually works better IMO. You'd want that clarified: for a specific
platform...
Almost everyone except you, apparently.

Hmm, no response to key questions...

The two points were:

A) How do you write portably when 1) even portable C code is only so
portable, 2) you cannot test the code on other difficult systems anymore,
and 3) the only way to detect many of these issues today is by compiler
warnings?

I found a way to test EBCDIC. Unfortunately, I don't have it setup. But, I
can't test on a Cray. Or, old IBM "iron". etc. So, if I've got code in
which I mistakenly treated a pointer to a struct and a pointer to a union
(or some other type) to be equivalent and if the compiler doesn't warn me
that this is non-portable, how do I determine that the code is non-portable?

B) Why should you even attempt to support a non-x86 platform today?

x86 is the dominant platform. Both the dominant x86 and modern non-x86
platforms use the same basic memory and I/O architectures that were in use
at C's creation. If fact, almost all microprocessor based platforms back to
1974 do. It's the obsolete miniframes, mainframes, and obscure hardware
platforms, non-ASCII platforms, and those that used a central processing
unit, that didn't.
But you're
advocating removing features from the C language that exist for
the purpose of enabling portable code.

What?

While there is _much_ in C that shouldn't be used for many reasons IMO, I do
not recall explicitly mentioning the _removal_ of anything. That's a
conclusion you deduced.

Would C have been better off if it only had a single file mode? I think so.
Except for boundary cases, like carriage return, linefeeds, and newlines,
the C code for text and non-text could would be of a single form or style.
And, the boundary cases would be well known and well preserved in the code -
perhaps in simple #ifdef code sections... I'd guess that if that had been
done, we might've even seen a new standardized header containing all the
relevant info, perhaps as part of "C90". That'd have been much better for
portability, don't you think?


Rod Pemberton
 
R

Rod Pemberton

Ben Bacarisse said:
How can you tell the difference between a \r that is (or is part of) a
line ending and one that is there in its own right?

Why would non-text character be in a text file if it's not a control
character, e.g., used for a line ending or formatting? I.e., how can \r - a
line ending control character - be "there in it's own right" - when if it
was it'd be a line-ending control character? That makes no sense.

When converting between systems using ASCII with different line endings: CR,
LF, and CRLF, the algo. to fix them is simple. Delete CR. Set a flag that
you saw a CR. Emit the appropriate line ending sequence (CR, LF, or CRLF),
if or when an LF occurs. This emits the correct sequence for LF and CRLF as
line endings. If the current character is not a control character and the
last character was a deleted CR, emit the appropriate line ending sequence.
This emits the correct sequence for CR as line ending.


Rod Pemberton
 
B

Ben Bacarisse

Rod Pemberton said:
Why would non-text character be in a text file if it's not a control
character, e.g., used for a line ending or formatting? I.e., how can \r - a
line ending control character - be "there in it's own right" - when if it
was it'd be a line-ending control character? That makes no sense.

Yes, that makes no sense. Fortunately for me that is not what I am
saying :)

Why do you think that a \r can't be there "in it's own right"? \r can
appear in a character literal or a string and C gives the sequence a
specified meaning. It does not have to map to a particular code and
it should not be taken to be part of line ending (though that last
rule was, if I recall correctly, sometimes broken in early C
implementations).

To take an extreme example: if stdout is a text stream, the call
puts("a\rb\r\n"); should generate one line on all systems. That line
should have four characters in it followed by whatever line ending the
system uses.

bartc was describing a system that the solved a problem for him but it
sounded to me as if it would interfere with strings like the one above
that contain embedded \r sequences.
When converting between systems using ASCII with different line endings: CR,
LF, and CRLF, the algo. to fix them is simple. Delete CR. Set a flag that
you saw a CR. Emit the appropriate line ending sequence (CR, LF, or CRLF),
if or when an LF occurs. This emits the correct sequence for LF and CRLF as
line endings. If the current character is not a control character and the
last character was a deleted CR, emit the appropriate line ending sequence.
This emits the correct sequence for CR as line ending.

That is one conversion algorithm but I would not use it in general.

Ideally, I would want to know which line end convention was used in
the source and I'd map that to the one required by the target. If the
source convention is not known then one can try to deduce it by using
heuristics.
 

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
474,102
Messages
2,570,641
Members
47,245
Latest member
LatiaMario

Latest Threads

Top