Programming in standard c

J

jacob navia

Dann said:
Simh performance is vaxlike, though (ugh!). You can get an nice DS10L from
here for a cheap price:
http://www.islandco.com/alpha_systems.html

Look at that:

AlphaServer DS10L Noname pc clone (my machine)
466Mhz CPU EV6 2GHZ Dual core AMD
256MB Memory 2GB memory
30GB IDE 7200RPM Disk 1000 GB disk storage
Dual Serial Port 2 USB
Dual 10/100 Ethernet Dual 100 Ethernet
1 Open PCI Slot 3 PCI slot
Power Cord Power cord, keyboard, mouse
1 Year Island Warranty 1 year warranty

$699 600 Euros
 
Y

ymuntyan

jacob navia said:



No, nobody insists on any such thing, and nobody is forcing anyone to do
anything. If you want a system-specific solution, you can have one,
because implementors provide them for such tasks as getting the file size
in a way meaningful on the system they are targeting. But those who need a
truly portable solution are not able to make the kinds of assumptions that
you seem to think are reasonable. You may have the luxury of choosing the
hardware you will target, but not everyone else has that luxury. You might
be able to say "I wouldn't be seen dead using such a stupid system", but
other people do have to use systems that you wouldn't be seen dead using.
C does not abandon them.

One could say that C shouldn't provide any file operations at
all, and let vendors provide extensions for that, since it may
not make sense to "open a file" on some systems. What exactly
is the difference between fopen() and fgetfilesizeforJN()
(except the obvious one, that one is standard, and the other
one is imaginary)? Sure thing, getting a thing like stat() into
the standard would be an incredibly hard task, but it's not the
kind of things you are talking about, is it?

Yevgen
 
D

Dann Corbit

One could say that C shouldn't provide any file operations at
all, and let vendors provide extensions for that, since it may
not make sense to "open a file" on some systems. What exactly
is the difference between fopen() and fgetfilesizeforJN()
(except the obvious one, that one is standard, and the other
one is imaginary)? Sure thing, getting a thing like stat() into
the standard would be an incredibly hard task, but it's not the
kind of things you are talking about, is it?

Opening a file is (in a sense) inherently non-portable.
Indeed, in the case of a toaster IC, there may be no such concept available.
However, on systems like that, the non-hosted rules apply.

Every C program pretty well needs to be able to open a file if it wants to
work with anything other than the three already opened files (stdin, stdout,
stderr). The functionality of fopen() must therefore be present to get just
about anything useful done.

Quite likely, system specific file operations will also be available under
OS specific APIs (e.g. sys$open() in lieu of fopen() on OpenVMS or
CreateFile() in Win32).

These functions will (no doubt) be supplied by the compiler vendor.
 
R

Ravishankar S

You can't do *anything* in just standard C.

This is quite true in case of embedded systems. The standard does not seem
to have the notion of
object files, sections, addressing modes and linking.
 
U

user923005

This is quite true in case of embedded systems. The standard does not seem
to have the notion of
object files, sections, addressing modes and linking.

Those difficulties exist whether or not C is for embedded systems.
Tools like editors, debuggers, and linkers are not discussed in the
standard. However, both the translation environment and the execution
environment are discussed, and so compiling and linking are somehow
implied, at least. This is especially so during the last pass of the
translation environment:

"8. All external object and function references are resolved. Library
components are linked to satisfy external references to functions and
objects not defined in the current translation. All such translator
output is collected into a program image which contains information
needed for execution in its execution environment."

and section:
"5.1.2 Execution environments"
which covers both hosted and freestanding versions.
 
C

CBFalconer

.... snip ...

One could say that C shouldn't provide any file operations at
all, and let vendors provide extensions for that, since it may
not make sense to "open a file" on some systems. What exactly
is the difference between fopen() and fgetfilesizeforJN()
(except the obvious one, that one is standard, and the other
one is imaginary)? Sure thing, getting a thing like stat() into
the standard would be an incredibly hard task, but it's not the
kind of things you are talking about, is it?

What is wrong with a system that provides stdin, stdout, and
stderr? fopen always returns NULL, as does fclose. You can access
fgetc, getc, fputc, putc. Cuts the library size down like magic.
 
C

CBFalconer

jacob said:
Look at that:

AlphaServer DS10L Noname pc clone (my machine)
466Mhz CPU EV6 2GHZ Dual core AMD
256MB Memory 2GB memory
30GB IDE 7200RPM Disk 1000 GB disk storage
Dual Serial Port 2 USB
Dual 10/100 Ethernet Dual 100 Ethernet
1 Open PCI Slot 3 PCI slot
Power Cord Power cord, keyboard, mouse
1 Year Island Warranty 1 year warranty

$699 600 Euros

Well, you might buy the DS10L if you want a quick upgrade. You
will probably find it much more reliable. I have a strong
suspicion you can mount almost all the disk drives you want. I
note it has real serial ports, which are missing on many machines.
It probably also has a real floppy drive available.

It is actually cheaper than your machine. Euros are worth about
$1.40 today.
 
R

Richard Heathfield

jacob navia said:
Richard Heathfield wrote:


This is exactly the levelling by the worst.

Of course "C does not abandon them". They have just to
1) open the file
2) Read until they hit...
3) EOF!

Either you are trying hard not to understand, or you forgot to read my
previous reply.
 
R

Randy Howard

This system is a good example of a currently widely
used system isn't it?

The solution for that system is very simple.
filesize reports number of blocks times the size of each block.

Period. Of course this is not the size of the useful bytes but...
who cares? CP/M users know that!

so what?

filesize searches till the end of the file is found or if the device is
not supported returns an error.

See also resource forks on mac file systems.

What is obvious is that there are two alternatives:

1) Take the worst possible file system. Then standardize only
what that file system supports.

2) Take the most common situation for current machines and file
systems and standardize what those systems support.

Note that if you choose two, you pretty much guarantee that this
mythical language isn't portable. As that seems to be your end goal in
all these threads, I'm not surprised you propose it.
For instance, and to go on with CP/M you could store the number
of used bytes in each block at the last 2 bytes of each block
isn't it?

Not very difficult to do.


Yeah, let's go modify an OS that's been around for decades, along with
several others of both older and new vintage, along with all code for
them impacted by your changes, so that you can manage to write a
program portably, where others can do so without cracking open OS
internals to get there.

*sigh*
 
R

Randy Howard

Someone creates a new OS with a file system having the innovative idea of
storing the byte-size of each file.

The question is, why would they do that? Because nobody would be allowed to
make use of it; not in Standard C anyway. Or other languages because they
are likely also implemented in C.

How then would a C programmer take advantage of this feature even though
it's only available on a billion or so computers?

The same way a C programmer (or any other language programmer takes
advantage of platform-specific extensions which are, by definition, not
portable, and don't appear in any standardized cross-platform languages
as a core interface.
 
R

Robert Latest

jacob said:
There is no point in discussing with somebody that doesn't want
to go into the arguments of the other side.

There is no point in discussing a problem that nobody but one person seems
to have, especially if that one person has already solved it for himself...
All multi user OSes provide a "stat" function.

....whereas most others can rely on a proven out-of-the-box solution.

Everybody else can reliably solve the problem (gobble up an entire file in
RAM) in a ten-liner. If that many.

robert
 
J

jacob navia

Randy said:
Note that if you choose two, you pretty much guarantee that this
mythical language isn't portable. As that seems to be your end goal in
all these threads, I'm not surprised you propose it.

I am not surprised you say this either. Till now, there hasn't been
ANY system where there wasn't an operation to get the file size.
VAX/VMS included. And if there was one, it could ALWAYS do
1) Open the file
2) Read until EOF

to get the file size. Granted, it wouldn't be efficient in some weird
systems but so what? It would be possible.
Yeah, let's go modify an OS that's been around for decades, along with
several others of both older and new vintage, along with all code for
them impacted by your changes, so that you can manage to write a
program portably, where others can do so without cracking open OS
internals to get there.

Nobody needs to modify the OS. But if those systems support C, they
MUST support

FILE *f = fopen("foo","a+");

And they HAVE to know where the end of the file is somehow. I am
amazed how you and the others just ignore the basic facts.

In C, any file is conceptually a sequence of bytes. Some file systems
do not support this well. But if they support it, THEN they must
ALREDY support this abstraction so that filesize wouldn't mean any effort.

You are making an alternative where only two bad possibilities exist
just to show your peers that you support the party line.
 
R

Randy Howard

Eric said:
jacob said:
[...]
You can't do *anything* in just standard C.

Then why do you bother with this newsgroup? Why do
you waste your time on a powerless language? Why don't
you go away and become a regular on comp.lang.mumps or
comp.lang.apl or any newsgroup devoted to a language you
consider more useful than C? Since C has zero utility
(in your stated estimation), even comp.lang.cobol would
be a forum of more value. Go! Spend your talent on
something more useful than the torment of us poor old
dinosaurs! Go!

Stop whining and see the sentence in my message:
<quote>
This confirms my arguments about the need to improve the quality
of the standard library!
<end quote>

The solution for me is to improve what is there.

Ok, then. If you are correct, then you should be able to release and
sell a "All the World's an Intel" library for "real C programmers" to
use, along with those that have tried and failed to write anything in
standard C, if they exist. If they exist in the numbers you believe
they do, then you should clean up financially. Stop encouraging others
to compete with you, and go do it.

Hint: Most of us that have been writing portable C programs for ages
already have "kitchen sink" libraries of our own, that do many of the
things that frequently need doing, but are not done the same way on a
dozen or more platforms that we have had to support, still support, or
will need to support in the near future.
Every time I point out something that needs to be improved
the regulars are unable to put any coherent argumentation.

Factually incorrect. Every time you propose something, you propose a
solution that:
a) works only on your pseudo-C compiler and on no other compiler
b) something that is not portable at all, and works on win32, if you're
lucky.
c) is hopelessly naive, failing to recognize the existence of anything
outside of your immediate experience.

That's not very interesting, and lots of coherent arguments have been
put forth by many of the regulars. Your inability to realize it is
/not/ their fault.

There's an old joke, which is sadly not actually funny in your case,
hitting too close to home... "I can explain it to you, but I can't
comprehend it for you."
 
R

Robert Latest

jacob said:
Nobody needs to modify the OS. But if those systems support C, they
MUST support

FILE *f = fopen("foo","a+");

And they HAVE to know where the end of the file is somehow. I am
amazed how you and the others just ignore the basic facts.

They also have to support fseek, ftell and friends. What's not to like?

robert
 
R

Robert Latest

Randy said:
Factually incorrect. Every time you propose something, you propose a
solution that:
a) works only on your pseudo-C compiler and on no other compiler
b) something that is not portable at all, and works on win32, if you're
lucky.
c) is hopelessly naive, failing to recognize the existence of anything
outside of your immediate experience.

d) already exists as a two-liner.

robert
 
R

Randy Howard

I am not surprised you say this either. Till now, there hasn't been
ANY system where there wasn't an operation to get the file size.

So you have verified this on every single system?
VAX/VMS included. And if there was one, it could ALWAYS do
1) Open the file
2) Read until EOF

to get the file size. Granted, it wouldn't be efficient in some weird
systems but so what? It would be possible.

You really should look at resource forks, then explain how a single
"answer" for file size would meet the "common" desired answer, and the
technically accurate one at the same time for files using them.

Not all the world sees files as you seem to think it does, hence your
confusion.
Nobody needs to modify the OS. But if those systems support C, they
MUST support

FILE *f = fopen("foo","a+");

And they HAVE to know where the end of the file is somehow. I am
amazed how you and the others just ignore the basic facts.

What I am /not/ ignoring is your comment above that implies that CP/M
should store its file data differently than it in actuality does.
 
C

Chris Torek

/*
function to slurp in an ASCII file
Params: path - path to file
Returns: malloced string containing whole file
*/

I think we can improve this a great deal, with the result being
a function that is written entirely in Standard C and works in
every case in which it is possible for it to work, and -- by
calling a system-dependent function that the user is to supply,
but which may be replaced with a #define that simply returns 0
if desired -- is "reasonably efficient" as well.
char *loadfile(char *path)
{
FILE *fp;
int ch;
long i = 0;
long size = 0;
char *answer;

fp = fopen(path, "r");
if(!fp)
{
printf("Can't open %s\n", path);
return 0;
}

In a posting I read earlier, Julienne Walker wrote a version
that used a user-supplied "FILE" instead of a name. I think
this is superior, since it allows one to skip over some initial
portion of the file. (It also eliminates the question of what
to do if the file cannot be opened.) So let us do that:

char *loadfile(FILE *fp, size_t *sizep) {
size_t n; /* number of bytes read so far */
size_t space; /* amount of space allocated */
char *buf; /* the buffer we are working with */
char *new; /* for realloc()ing */

Now we come to what I see as the real "point of argument" here.
We would like to get an "estimate" of the size of the file, so that
we can do a single malloc() to hold the contents. Of course at
this particular point, we might like to subtract any initial offset
as well -- but we do not know how to convert the result of ftell()
or fgetpos() into such a number, so I will just proceed as if the
"initially-skipped count" is always zero. (If loadfile() is to
open the file, this is correct; if loadfile takes an already-open
file as above, we could always add a "skipped bytes count" argument.)

Here is where the system-dependent function comes in:

size_t estimate = estimate_file_size(fp);

The "estimate_file_size" function can use fstat() (on POSIX
systems), or "SYS$GETFILEMETADATA" on some other system, or
we can just do:

#define estimate_file_size(fp) 0

because the result is only assumed to be an *estimate*, rather than
an exact answer. As a nice bonus, this means that, e.g., on POSIX
systems, where fstat() returns a handy exact answer that is entirely
wrong if the file is being modified as we read it, the code still
works.
answer = malloc(size + 100);
if(!answer)
{
printf("Out of memory\n");
fclose(fp);
return 0;
}

Instead of adding 100, we just use the estimate (plus 1 for the
'\0'). In case the estimate is zero, though, we use 1 (plus the
same 1).

To indicate failure, we return NULL (as you do here) but
do not print an error message, since general-purpose library routines
usually should not do so (the error may need to be logged rather
than printed, for instance):

if (estimate == 0)
estimate = 1;
space = estimate;
buf = malloc(space + 1);
if (buf == NULL)
return NULL;

(Since we eliminated the issue of opening the file, a NULL return
always means "unable to read", either due to an I/O error or due
to malloc() failure.)
while( (ch = fgetc(fp)) != EOF)
answer[i++] = ch;

Now we get to the part that deals with the fact that the estimate
is merely an estimate:

for (n = 0;;) {
size_t nsuccess, nattempt;
int c;

/*
* Attempt to fill in the rest of the buffer.
* We have read "n" bytes so far and we have
* space for "space" bytes (plus 1 extra, not
* counted in "space").
*
* If the read fails, we get a short count or
* zero. A short count could indicate normal EOF
* or an I/O error, so we must use feof() and
* ferror() to tell them apart.
*
* If we get everything we asked for, we hope
* that we are now at EOF, but we may not be,
* so check.
*/
nattempt = space - n;
nsuccess = fread(buf + n, 1, nattempt, fp);
n += nsuccess; /* we now have read this many */

if (nsuccess < nattempt) /* normal EOF or I/O error */
break;
c = getc(fp);
if (c == EOF) /* normal EOF or I/O error */
break;

/*
* Our estimate must have been too low. We actually
* have room to save c, so do that now, then enlarge
* the buffer and try again.
*/
buf[n] = c;
estimate *= 2; /* or any other suitable increase */
new = malloc(estimate + 1);
if (new == NULL) {
free(buf);
return NULL;
}
buf = new;
space = estimate;
}

We exit the above loop only on normal EOF or error (or, in a sense,
if the malloc() fails, but in that case we return to the caller,
rather than ending the loop). So now we check which is the case:

/*
* It might make for better flow to move the ferror() test
* here and let the non-ferror(), i.e., feof(), case be the
* last code in the function. I thought it was interesting
* to use feof() correctly in comp.lang.c for once, though. :)
*/
if (feof(fp)) {
/*
* All is well -- we successfully read the entire file.
* Optionally, we can realloc down here:

new = realloc(buf, n + 1);
if (new != NULL)
buf = new;

* This usually saves a few bytes when the estimate is poor,
* and always saves one byte when the estimate was 0
* (including for actually-empty files), but tends to
* cost runtime. (Of course, it would also make sense
* to see if n differs from the estimate first.)
*/
buf[n] = '\0';
if (sizep != NULL)
*sizep = n;
return buf;
}

/*
* Since the loop terminated, but feof(fp) was not set, we
* must have had some kind of error (bad floppy disk?) while
* reading the file. Here, I choose to discard the data read
* so far and return NULL, but there may be reasons to do
* other things. In general, however, error recovery is
* extremely system-dependent.
*/
free(buf);
return NULL;
}

At the risk of redundancy, here is the complete function, with
a leading comment added, and the extensive internal commenting
shrunken down. I also removed the "estimate" variable as it is
essentially the same as the "space" variable.

The following is entirely untested. :)

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

/*
* Load from an existing opened file into memory, adding a
* terminating '\0' to make the result a valid C string. If
* sizep is non-NULL, set it to the number of bytes loaded
* (not including the terminating '\0').
*
* Returns NULL on failure, in which case *sizep is not useful.
*/
char *loadfile(FILE *fp, size_t *sizep) {
size_t n; /* number of bytes read so far */
size_t space; /* amount of space allocated */
char *buf; /* the buffer we are working with */
char *new; /* for realloc()ing */

space = estimate_file_size(fp);
if (space == 0)
space = 1; /* must attempt to read, even if empty file */
buf = malloc(space + 1);
if (buf == NULL)
return NULL;

/*
* If the estimate is 100% accurate or over-estimates,
* this loop runs only once. (If the estimate *is*
* accurate and all goes well, the getc() returns EOF.)
*/
for (n = 0;;) {
size_t nsuccess, nattempt;
int c;

/*
* Attempt to fill in the rest of the buffer. Note that
* fread() returns a short count or 0 on EOF or error.
*/
nattempt = space - n;
nsuccess = fread(buf + n, 1, nattempt, fp);
n += nsuccess;

/*
* Terminate loop on EOF or error. If the estimate was
* right, we have to attempt one more byte to see the EOF.
*/
if (nsuccess < nattempt || (c = getc(fp)) == EOF)
break;

buf[n] = c; /* under-estimated -- save c and expand */
space *= 2;
new = malloc(space + 1);
if (new == NULL) {
free(buf);
return NULL;
}
buf = new;
}

if (ferror(fp)) {
/* I/O error -- not dealt with very well here. */
free(buf);
return NULL;
}

/* Loop ended, and not due to error, so must be normal EOF. */
#ifdef OPTIONAL
if (n < space) {
new = realloc(buf, n + 1);
if (new != NULL)
buf = new;
}
#endif
buf[n] = '\0';
if (sizep != NULL)
*sizep = n;
return buf;
}
 
R

Richard

user923005 said:
Imagine a Z/OS machine with a 1000 GB file. Do you know how much this
operation will cost and how long it will take?


Then the file size changes one microsecond later. What do they do
with this very expensive measurement that they have made?

How ridiculous. This is true for many things. Always "file size" in
"portable C" is useless. This is what Jacob is alluding to.
Perhaps a system specific function can do a much better job. Perhaps

You seem to miss the point. filesize(fp) is portable if it's in the
standard. How it is implemented per platform is another issue.
a generic function cannot produce a reliable answer. I guess that
other people have thought about this question and figured out that a
reliable file size function cannot be written in a generic manner.

Rubbish. All files have a byte size. And the "size" returned for a
specific platform will be well documented with regard to padding bytes
or whatever.
No. Portability is very important for the part of the code that can
be made portable. But getting the job done is very important so it is
sometimes a requirement to use something that is not part of any
standard.


Noone has ever said this. A portable file size function that gives a
correct answer is clearly impossible.

How silly.

"correct" would be platform specific. The API need not be.
 
B

Bart C

Chris Torek said:
I think we can improve this a great deal, with the result being
a function that is written entirely in Standard C and works in
every case in which it is possible for it to work, and -- by
calling a system-dependent function that the user is to supply,
but which may be replaced with a #define that simply returns 0
if desired -- is "reasonably efficient" as well. ....
At the risk of redundancy, here is the complete function, with ....
char *loadfile(FILE *fp, size_t *sizep) {
.....

Of course in practice one would write:

char *loadfile(FILE *fp, size_t *sizep) {
if (thisiswindows) /* or other capable OS */
/*do it in a dozen lines */
else
/*do it the hard way*/
}

The return value in *sizep is still a little worrying because according to
user923005 this information is useless, if it's assumed to bear any relation
to the size of the file just read, because that size could change any time.

Bart
 

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,432
Messages
2,571,681
Members
48,796
Latest member
Greg L.

Latest Threads

Top