473,405 Members | 2,141 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

C, really portable?

Is C really portable? And, apologies, but this is possibly a little OT?

In c.l.c we often see 'not portable' comments, but I wonder just how
portable C apps really are.

I don't write portable C code - *not only* because, in a 'C sense', I
probably do things that aren't portable - but because for the last x years,
I've written code to run on a number of different platforms. Those apps
have had to make use of system calls, use threads, present nice UIs, .

Premise: any decently complex modern application cannot be entirely written
in standard C [meaning, the language without compiler added 'extensions',
and only using the standard libraries]. Or, if it is written in standard C,
then it is 'sub optimal' [and certainly doesn't have a nice UI!].

Conclusion: Whilst the language is portable, applications are not. And
that's why we also often see 'go and ask elsewhere' comments appearing here
[totally reasonable they are too of course].

Anyway, just a thought, and I wonder if anyone can come up with a counter to
it?
Dec 9 '05
131 5988
Netocrat <ne******@dodo.com.au> writes:
On Sun, 11 Dec 2005 11:08:33 -0500, Eric Sosman wrote:
[discriminating fprintf errors]
f = fprintf(....);
if (r < 0) {
perror ("fprintf"); /* debatable */
...
}

The perror() call is dubious because the Standard doesn't
require that fprintf() set errno to anything meaningful.


It does guarantee that fprintf won't set errno to zero though (it may set
it to non-zero). So the code could be extended:

errno = 0;
f = fprintf(....);
if (r < 0) {
if (errno > 0)
perror ("fprintf"); /* debatable */
else
fputs(stderr, "fprintf: unspecified error");
...
}


You probably want "if (errno != 0)". I don't see anything in the
standard that prohibits setting errno to a negative value, though the
values EDOM, EILSEQ, and ERANGE are required to be distinct and
positive. (I think using only positive values for errors is common
practice, though.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 11 '05 #101
"Malcolm" <re*******@btinternet.com> writes:
"P.J. Plauger" <pj*@dinkumware.com> wrote

[...]
Excuse me, but you made two statements about things that go on
inside my head. And you happen to be wrong. You're defending them
by stating opinions that come from inside *your* head. And I
happen to believe most of those opinions are not supported in
the real world. I am undisputably the world's foremost authority

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
on what goes on inside my head. You seem to have problems

^^^^^^^^^^^^^^^^^^^^^^^^
distinguishing my reality from your personal reality from the
real world we both inhabit. I try not to.

How do you know you are not suffering from a mental illness?


I won't try to guess what you actually meant by that remark, but it
could easily be interpreted as a personal insult, and I think we've
seen more than enough of that in this thread.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 11 '05 #102
Eric Sosman wrote:
Keith Thompson wrote:
Emmanuel Delahaye <em***@YOURBRAnoos.fr> writes:
jacob navia a écrit :

Is this code snippet portable?
int a,b,c;
...
a = b+c;
no, because b and c are not initialized. The behaviour is undefined.


Presumably the "..." represents code in which b and c have values
assigned to them. jacob said it was just a snippet.

Yes, but since the supposed non-portability depends
entirely on the elided material, it's a silly snippage.
That, I think, is Emmanuel's point.

No. In general integer overflow error is not handled at all
in C, contrary to floating point overflow,
where you can use the fegetenv functions to query
the overflow flag.

This distinction between integer overflow and floating point
overflow is quite surprising. Why a detail like the machine
representation would make any difference? Nowhere is that
explained.

The code I showed was just a short way of telling people what I am
speaking about. The "..." represents omitted code that assigns
some values to those variables. A more complete code snippet would
be:

int fn(void);
int fn1(void);
int a,b=fn(),c=fn1();
a = b+c;

I.e. b and c contain *some* integer value.

This was shortened to
int a,b,c;
....
c = a+b;

It was clear what I am speaking about, but instead of
concentrating in the discussion topic, you choose to
make as if this was not clear.
Dec 11 '05 #103
On Sun, 11 Dec 2005 23:46:05 +0100, in comp.lang.c , jacob navia
<ja***@jacob.remcomp.fr> wrote:

I wanted to show how difficult is to write anything really portable
because of the absence of error analysis standards in C.


And instead all you've shown is that you don't have much idea what
portability is.
----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Dec 11 '05 #104
"P.J. Plauger" <pj*@dinkumware.com> writes:
"Richard Heathfield" <in*****@invalid.invalid> wrote in message
news:dn**********@nwrdmz02.dmz.ncs.ea.ibs-infra.bt.com...
Malcolm said:
"Richard Heathfield" <in*****@invalid.invalid> wrote in message
news:dn*********@nwrdmz02.dmz.ncs.ea.ibs-infra.bt.com...
P.J. Plauger said:

> Get stuffed.

I commend this imperative to the attention of those ladies and gentlemen
of comp.lang.c who have hungry sigmonsters.


<context re-snipped>
Authors of C textbooks are valauble people on the ng, and shouldn't be
insulted, wouldn't you agree?


Not necessarily - imagine Schildt becoming a clc regular! But if you think
I
was complaining at Mr Plauger's reaction to Hsieh's insulting behaviour,
think again. It was in fact rather more low-key and restrained than Hsieh
deserved.

No, I just thought that, from such an eminent source, this would make an
excellent quote for people who like collecting them. It is a quote that
will mature with the years, as the context fades from memory.


Aw, shucks. And I was just trying to be rude.


Cool, more siq quote fodder!

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 11 '05 #105
On Mon, 12 Dec 2005 00:14:38 +0100, in comp.lang.c , jacob navia
<ja***@jacob.remcomp.fr> wrote:
This distinction between integer overflow and floating point
overflow is quite surprising.
Only if you don't know much about how different architectures handle
integers. Again, I think the problem is that you have a limited
experience from which you're trying to generalise.
Why a detail like the machine
representation would make any difference? Nowhere is that
explained.


Why shold it be? The Standard is the standard, not the rationale.
----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Dec 11 '05 #106

In article <dn**********@news.ox.ac.uk>, "pemo" <us***********@gmail.com> writes:

Premise: any decently complex modern application cannot be entirely written
in standard C [meaning, the language without compiler added 'extensions',
and only using the standard libraries]. Or, if it is written in standard C,
then it is 'sub optimal' [and certainly doesn't have a nice UI!].


It's possible to write a number of "decently complex modern
application[s]", at least as I'd define that phrase, in standard C.
Compilers can generally be written entirely in standard C; their
output may or may not be useful on multiple platforms, but the
programs themselves are portable.

I could write an interpreter for a scripting language entirely in
standard C. It would be limited to the facilities available to
standard C programs, and those that can be constructed upon them,
but that's quite a lot.

I could write an HTTP server entirely in standard C (I think - I
don't believe there's anything in RFC 2616 that would prevent that,
at least for a conditionally-compliant implementation), if it could
use stdio for its I/O, which is easy to do on Unix (using inetd).
And it could even have a GUI for administrative tasks (implemented
in HTML, Javascript, etc, and served up via HTTP), if that's what
you mean by "nice UI". (It's not what *I* would mean by "nice UI",
since I generally think GUIs and the like are a tremendous waste of
my time, but that's a different matter.)

And even if you want to exclude a system facility for doing network
I/O via stdio (which, in my opinion, would be changing the original
requirements), you'd still have an HTTP interpreter, which could be
very useful for such things as testing HTTP user agents.

Most applications use non-standard facilities, true. Probably most
of them benefit from them in some way. But that doesn't mean that
there aren't any interesting ones that can be written in standard C.

--
Michael Wojcik mi************@microfocus.com

Pogo: The dogs *scarcely* ever catches the rabbit.
Bun: "Scarcely" got a very unpleasant ring of frequency to it.
-- Walt Kelly
Dec 11 '05 #107
jacob navia wrote:
Eric Sosman wrote:
jacob navia wrote:
The standard would define a RANGE of values dedicated to specific errors
so that the calling program could determine what type of failure
happened, INDEPENDENTLY from the specific printf implementation.
This would require that the Standard enumerate all
categories of errors -- maybe not every single possible
error, but at least all categories. Categorization involves
simplification: By lumping umpty-mumble errors into a single
category, you lose those errors' individual identities. Now,
you're evidently discontented with the ultimate simplification
and identity loss of "An error occurred," and would prefer to
discriminate more finely. Do you imagine that the level of
detail that satisfies you would satisfy everyone else?

Setting aside ranges rather than individual values solves
anything. You are (apparently) happy to lump all "I/O errors"
together, so long as they're distinct from "format errors."
Someone else might want to distinguish "logical I/O errors"
(disk full, security violation, ...) from "physical I/O errors"
(SCSI bus reset, modem hangup, ...), and this would require
subdividing your {MIN,MAX}_PRINTF_IOERROR range. And the next
guy would want to separate "real hardware errors" from "network
errors," and subdivide the subdivided ranges ... When you arrive
at the point where each range contains just one element, you're
back to enumerating every error again.


Since the errors are in a RANGE of numbers, and we have at least 16
bits in an int, we can easily make up ranges big enough to accomodate
for a LOT of error codes, 32767 in fact. The standard would define
several ranges, and leave a lot of logical eror code space unused
for the implementations to use.


My point is that you can't cram all the distinct errors
into a mere 32767 codes without discarding information. You
think that C discards too much, and propose a richer set of
error codes. But are you the final authority on what might
be interesting? You'd like to distinguish "disk full" from
"icky format string," but the next guy would also like to know
which disk filled up, or at which character position the format's
ickiness became evident.
It is absolutely not necessary for the standard to enumerate all
categories but the most probable ones: i/o and format errors, like
missing specifier for the conversion, etc. This two ranges would
suffice for most applications and would improve what is possible
in standard C...


I am not claiming and have not claimed that C's way of
reporting errors is ideal. I will freely grant that it would
be useful to be able to distinguish some kinds of programming
errors from some kinds of "environmental" errors. But I am
still not persuaded that the current state of affairs makes
"reasonable usage [...] impossible," nor that the shortcomings
present any barrier to portability.

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 11 '05 #108
On 2005-12-11, jacob navia <ja***@jacob.remcomp.fr> wrote:
Eric Sosman wrote:
Keith Thompson wrote:
Emmanuel Delahaye <em***@YOURBRAnoos.fr> writes:

jacob navia a écrit :

> Is this code snippet portable?
> int a,b,c;
> ...
> a = b+c;
no, because b and c are not initialized. The behaviour is undefined.

Presumably the "..." represents code in which b and c have values
assigned to them. jacob said it was just a snippet.

Yes, but since the supposed non-portability depends
entirely on the elided material, it's a silly snippage.
That, I think, is Emmanuel's point.

No. In general integer overflow error is not handled at all
in C


But it is possible to guarantee that there is no overflow, depending on
what is in the elided code segment.
Dec 11 '05 #109
jacob navia wrote:
Malcolm wrote:
"Eric Sosman" <es*****@acm-dot-org.invalid> wrote
The only way to keep the list to a manageable length is
to group multiple error conditions together -- and as soon
as you do so, of course, you're suppressing information
about the "root cause" error. You keep mentioning a "disk
full" error -- but is that really the root cause? No, the
disk actually has plenty of room but your account has reached
its quota. Even that isn't the ultimate cause, because the
I/O system automatically contacted the billing system to see
if it could purchase some more quota for you on the fly, and
the ultimate I/O error is "Credit card rejected."

int r = printf("hello, world\n");
if (r < 0) {
switch (r) {
case IOERR_DISK_FULL: ...; break;
case IOERR_OVER_QUOTA: ...; break;
case IOERR_NETWORK_FAILED: ...; break;
case IOERR_DISK_FAILED: ...; break;
/* etc. */
}

What, exactly, would replace each set of ellipses, and how
would your handling of IOERR_BAD_MEMORY_PARITY differ from
IOERR_BLACKBERRY_LOST_PATENT_FIGHT_AND_TERMINATED_ SERVICE?

So what the user wants is

"This program could not complete because the disk is full. You have
arranged to purchase disk space on demand, but your automatic credit
card debit was rejected owing to insufficient cleared funds."

That tells him what the problem is, and how to rectify it. As you say,
it is very difficult to do this portably. However it could be done -
for instance, we could specify a library function
"stdouterrormessage()" that did just that.

Very funny.

What do you do with
fprintf(somefile,...);

1) You do not test the result. Anyway, a disk full is something never
happens, not to you anyway.


It depends on the circumstances. I try to apply a
level of testing that is calibrated to the importance
of the output. I cannot recall ever checking the value
returned by fprintf(stderr,...), for example, but I
certainly have checked whether the "main business"
output succeeded. (Sometimes I use ferror() instead of
checking every single fprintf(), but in any event I see
to it that there's an attempt to alert the user to a
problem.)
2) You code:
#ifdef LINUX
#ifdef TRIO_PRINTF
if (r == ...)
#elif GCC_PRINTF
if (r ==...)
#elif defined(WINDOWS)
#ifdef LCC_WIN32
if (r == ...)
#elif defined(WATCOM)
#elif defined (GCC)

#endif

etc etc, ad nauseum!
Second time around on this one -- and after it's
already been refuted by counter-example, too.
3) If there is an error you do a sloppy job
like assuming any error is a disk full error.
Thanks for your assessment of my code. I'm just
the sloppiest guy going.
It is easy to show irony, much harder to discuss
correctly and understand what the other is
saying/proposing, and answering accordingly.

I wanted to show how difficult is to write anything really portable
because of the absence of error analysis standards in C.
Jacob, Jacob: THE ERRORS THEMSELVES ARE NOT PORTABLE!
This is
due, as this discussion demonstrates, to the mentality "error
analysis is for wimps". Macho programmers never have any errors,
and anyway it is not worth thinking about this, since errors
are messy.


This is nonsensical muttering and a retreat from rationality.

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 11 '05 #110

"Keith Thompson" <ks***@mib.org> wrote
Plauger
I am undisputably the world's foremost
authority
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
on what goes on inside my head.
^^^^^^^^^^^^^^^^^^^^^^^^
How do you know you are not suffering from a mental illness?


I won't try to guess what you actually meant by that remark, but it
could easily be interpreted as a personal insult, and I think we've
seen more than enough of that in this thread.

Why would it be an insult? It's the obvious riposte to the claim being made.
Dec 11 '05 #111
In article <43***********************@news.wanadoo.fr>
jacob navia <ja***@jacob.remcomp.fr> wrote:
Since ... we have at least 16 bits in an int, we can easily make
up ranges big enough to accomodate for a LOT of error codes, 32767
in fact. The standard would define several ranges, and leave a lot
of logical eror code space unused for the implementations to use.


Please go use VMS for several years. It *does* this. Once you
have experience with how it works (and when and how it fails),
*then* come back and propose putting it into a future C standard.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Dec 12 '05 #112
Eric Sosman wrote:
jacob navia wrote:
3) If there is an error you do a sloppy job
like assuming any error is a disk full error.

Thanks for your assessment of my code. I'm just
the sloppiest guy going.


Well, that's what *I* do <grin>.

I assume that if fprintf returns a negative value the disk
is full.

It is the only portable thing I can do without tying the
code to some specific printf implementation.

It would be much better if I could portable write

err = fprintf(...);
if (err == EOF) {
// no space. Erase temporary files
}

This could be encapsulated in a
int MyFprintf(FILE *f,char *fmt,...)
{
int err = fprintf(... /*call ellided*/);
switch (err) {
case EOF:
// No space. Erase temp files
break;
default:
// Other errors
}
return err;
}
Dec 12 '05 #113
jacob navia wrote:
Eric Sosman wrote:
jacob navia wrote:
3) If there is an error you do a sloppy job
like assuming any error is a disk full error.

Thanks for your assessment of my code. I'm just
the sloppiest guy going.


Well, that's what *I* do <grin>.

I assume that if fprintf returns a negative value the disk
is full.

It is the only portable thing I can do without tying the
code to some specific printf implementation.

It would be much better if I could portable write

err = fprintf(...);
if (err == EOF) {
// no space. Erase temporary files
}

You're assuming erasing the temporary files will free up space. How do you
know? C does not even have a concept of "disks".

On my Linux system, /tmp links to a memory device. It could also easily link
to a different disk partition. Erasing temporary files would do exactly
nothing to alleviate the problem.

Now, you could say that you *do* happen to know erasing the temporary files
will be a good idea, or that you are willing to assume it will be a good
idea most of the time. Even so, why are you so bent on being able to do this
portably?

If printf() returned a "CRC failed, bad media" error, erasing the temporary
files would clearly be pointless. In fact, it's unlikely you could do
anything about such an error. Would it help if we required implementations
to return such errors where able? Would you be angry at a vendor if printf()
did not return the "disk full" error when you are expecting it to, but
instead a generic error because the low-level write routines cannot detect
this particular situation?

Would it be so bad to have to call a non-portable "get free space on disk"
function and erase the temporary files if it was low? Why would having to
depend on system-generated error codes be so much better? Almost no error
that could be generated admits a portable error handler in the first place.

Facilities for error handling are important. I think that demanding that the
standard provide more specific ones will not be helpful, however, for all
the reasons others have already mentioned. Detailed error handling is useful
only when you know what sort of things can go wrong on the particular
platforms you're writing for, and then you'll have to introduce some
unportable assumptions in the first place.

The only thing the standard could be taken to task for is that it does not
require that printf() update errno on encountering an error. It does not
disallow this either, but it needlessly complicates error recovery in
response to printf() calls even where we do know what could go wrong.

S.
Dec 12 '05 #114
Skarmander <in*****@dontmailme.com> writes:
[...]
The only thing the standard could be taken to task for is that it does
not require that printf() update errno on encountering an error. It
does not disallow this either, but it needlessly complicates error
recovery in response to printf() calls even where we do know what
could go wrong.


The standard says that fprintf() "returns the number of characters
transmitted, or a negative value if an output or encoding error
occurred". It would be nice if it distinguished between output errors
and encoding errors. But personally, I don't think it's that big a
deal.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 12 '05 #115
On Sun, 11 Dec 2005 23:06:34 +0000, Keith Thompson wrote:
Netocrat <ne******@dodo.com.au> writes:
On Sun, 11 Dec 2005 11:08:33 -0500, Eric Sosman wrote:
[discriminating fprintf errors]
f = fprintf(....);
if (r < 0) {
perror ("fprintf"); /* debatable */
...
}

The perror() call is dubious because the Standard doesn't
require that fprintf() set errno to anything meaningful.
It does guarantee that fprintf won't set errno to zero though (it may set
it to non-zero). So the code could be extended:

errno = 0;
f = fprintf(....);
if (r < 0) {
if (errno > 0)
perror ("fprintf"); /* debatable */
else
fputs(stderr, "fprintf: unspecified error");
...
}


You probably want "if (errno != 0)".


I don't believe so.
I don't see anything in the standard that prohibits setting errno to a
negative value,
True, certain library functions may even do it in the absence of errors:

N1124,7.5 #3:

| The value of errno may be set to nonzero by a library function call
| whether or not there is an error, provided the use of errno is not
| documented in the description of the function in this International
| Standard.

(fprintf is not documented as setting errno)
though the values EDOM, EILSEQ, and ERANGE are required to be distinct
and positive.
There's also #2:

| errno ... expands to a modifiable lvalue171) that has type int,
| the value of which is set to a positive error number by several library
| functions.
(I think using only positive values for errors is common practice,
though.)


The wording of #2 seems to require a positive value for functions
documented as setting errno.

#3 also seems to require that a library function documented as setting
errno may only set it to a positive value, but it could be interpreted
purely as an allowance for functions that do not set errno rather than a
prohibition against functions that do set it (I don't subscribe to that
interpretation).

--
http://members.dodo.com.au/~netocrat
Dec 12 '05 #116
Netocrat <ne******@dodo.com.au> writes:
On Sun, 11 Dec 2005 23:06:34 +0000, Keith Thompson wrote:

[...]
You probably want "if (errno != 0)".


I don't believe so.
I don't see anything in the standard that prohibits setting errno to a
negative value,


True, certain library functions may even do it in the absence of errors:

N1124,7.5 #3:

| The value of errno may be set to nonzero by a library function call
| whether or not there is an error, provided the use of errno is not
| documented in the description of the function in this International
| Standard.

(fprintf is not documented as setting errno)
though the values EDOM, EILSEQ, and ERANGE are required to be distinct
and positive.


There's also #2:

| errno ... expands to a modifiable lvalue171) that has type int,
| the value of which is set to a positive error number by several library
| functions.


Ok, I missed that.

I'd still rather test for errno!=0 than errno>0. If errno *is*
somehow set to a negative value, it probably indicates an error (in
the code that sets errno if nothing else).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 12 '05 #117
In article <dn**********@canopus.cc.umanitoba.ca>,
Walter Roberson <ro******@ibd.nrc-cnrc.gc.ca> wrote:
In article <11**********************@f14g2000cwb.googlegroups .com>,
<we******@gmail.com> wrote:
apparently the Perl source code (which
is in C) is a horrendous mess to port to each platform. I.e., even
*after having been ported* its a pain in the ass to use, because of
platform compatibility problems. But these are not problems of the
Perl *language*, but rather the implementation, which of course, is
mostly related to poor portability of C itself.

Perl as a -language- includes a number of hooks to operating
system facilities, such as signals, fifos, pipes, subprocesses, sockets,
semaphores, and threads. These are, of course, non-portable,


Following up to myself, to reply to a different aspect of Paul's
comments:

Many of the problems with Perl -are- problems of the language.

Essentially, a lot of what Perl -is-, is an a attempt to put together a
(more or less) unified API to provide traditional Unix services, to
hide some of the interface differences under the rug, and to try to
provide usable replacements for facilities not present in some OSes.

Interfaces to facilities usually provided by operating systems pervade
perl, as fully fledged members of perl, with (for example) "open"
having the same theoretical status in the language as "socket". Perl
might have started life with a text-processing emphasis, but it outgrew
that a long time ago.

Perl does aim to increase portability, by hiding OS differences when
that can be done with a reasonable amount of effort. That's a good
thing, but in practice Perl is all a compromises. If there is something
in perl which does not or cannot work or which would take more
work than anyone has bothered to put in, then that thing just
drops out... and perl doesn't make any effort to provide mechanisms
to probe to find out whether some facility has or has not been
made available.

perl does have the advantage over C that perl has exceptions, so
you can attempt something and recover if it doesn't work.
perl does -not-, though, have any kind of unified error handling
such as being proposed by Jacob. You get whatever error the
implementation for that platform happens to return. Using Jacob's
example: perl's printf's error handling is defined only in terms
of the function returning true if the conversion suceeeded; none of
the sublayers referred to for printf have any more error control.
sprintf does not mention the possibilities of errors at all.
Perl is not designed as an operating-system-calling program as
such: it is more a "common look and feel", with no specific consistancy
about which platform's look or feel it emulates. I have, in the
past, encountered a small number of programs -designed- for calling
operating system functions and smoothly handling argument
validation and error control. [I seem to recall that the one on the
Honeywell L6*/ STS series was quite nicely designed, but that was
20 years ago so I might not have noticed deficiencies at the time.]
--
If you lie to the compiler, it will get its revenge. -- Henry Spencer
Dec 12 '05 #118
Keith Thompson wrote:
Skarmander <in*****@dontmailme.com> writes:
[...]
The only thing the standard could be taken to task for is that it does
not require that printf() update errno on encountering an error. It
does not disallow this either, but it needlessly complicates error
recovery in response to printf() calls even where we do know what
could go wrong.


The standard says that fprintf() "returns the number of characters
transmitted, or a negative value if an output or encoding error
occurred". It would be nice if it distinguished between output errors
and encoding errors. But personally, I don't think it's that big a
deal.

Well, the point is that if fprintf() did unambiguously update errno,
perror() would always work, and there would also be no reason to deal with
the negative value it returns (in non-standard code, of course); platforms
could return an error code, but this would be senseless duplication of the
errno functionality.

Still, this is more a QoI issue.

S.
Dec 12 '05 #119
Old Wolf said:
BTW, see the excellent post by Walter Roberson on how
non-portable most Perl programs are.


To be fair, most C programs are totally non-portable too. But then most C
programs are written by people who don't know C very well, who don't
realise just how portable well-written C programs can be, and who, quite
frankly, don't care.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Dec 12 '05 #120
jacob navia said:
Is a program just using printf portable? <code snipped>
The result of printf is negative if there was an error,
but the exact values are implementation specific and
will change from this implementation of printf to the
next one. This makes impossible any error analysis
of that function call in a portable way.


There are several reasons printf can fail. These reasons are not themselves
portable. On one system, it might be possible for printf to fail because a
disk has filled. On another system, printf might only ever fail if someone
forgot to feed the goat. When you bear in mind that systems yet to be
invented will have failure modes yet to be imagined ("Ae'm sarry capt'n,
but the neutrino laser's peptide tube has melted again, and it's messing up
all mae printfs"), it becomes clear that /no/ language can provide portable
error analysis.

C cannot make inherently non-portable concepts /become/ portable. Where it
scores highly is in retaining the portability that does already exist
within a problem. For example, it is known that printf can fail, albeit for
a variety of reasons. The /reasons/ are not portable, but the concepts of
success and failure /are/ portable, and C rightly lets us distinguish
between them.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Dec 12 '05 #121
On 2005-12-12, Skarmander <in*****@dontmailme.com> wrote:

[snip]
The only thing the standard could be taken to task for is that it does not
require that printf() update errno on encountering an error. It does not
disallow this either, but it needlessly complicates error recovery in
response to printf() calls even where we do know what could go wrong.


While I agree that the standard could perhaps be better in this regard,
if you really were planning on using errno for this, it would be
easy to provide a

*pseudocode*
int do_printf(...) {
int r;
r = printf(...);
if (r<0) errno = 1;
return r;
}

A pain I suppose, but so is manual memory management. If you want
C++/Perl/Pascal/Lisp/Prolog/Java/Haskell/Ada you know where to get them.

It would be nice though if all errors were either inline or via errno.

--
Nathan Wagner
Dec 12 '05 #122
On 2005-12-11, Keith Thompson <ks***@mib.org> wrote:
I wouldn't mind seeing some kind of exception handling mechanism in a future
C standard, though not one as elaborate as what C++ has.


Doesn't C have this already via longjmp()? It's basic and simple.

Is longjmp() used for anything other than error/exception handling?

--
Nathan Wagner
Dec 12 '05 #123
On Mon, 12 Dec 2005 02:08:31 +0000, Keith Thompson wrote:
[...]
I'd still rather test for errno!=0 than errno>0. If errno *is*
somehow set to a negative value, it probably indicates an error (in
the code that sets errno if nothing else).


Agreed (2nd sentence) - that's why the code prints "fprintf: unspecified
error" for negative errno's.

All the Standard specifies is that perror "maps the error number ... to an
appropriate error message string". The "appropriate" mapping for a
negative errno may be something like "unspecified error" anyhow, but OTOH
it may be "invalid negative error code".

OK, just realised I can check this... with gcc and glibc for errno of -1,
perror's mapping is "Unknown error 4294967295".

Eric Sosman raised the issue of confusing messages. I find "unspecified
error" more helpful than "Unknown error 4294967295", especially
considering that fprintf wouldn't have intended "4294967295" (really -1)
to have been interpreted as an error code.

--
http://members.dodo.com.au/~netocrat
Dec 12 '05 #124
Nathan Wagner wrote:
On 2005-12-11, Keith Thompson <ks***@mib.org> wrote:

I wouldn't mind seeing some kind of exception handling mechanism in a future
C standard, though not one as elaborate as what C++ has.

Doesn't C have this already via longjmp()? It's basic and simple.


Basic and simple, yes. The problem is that its
simplicity makes it hard to use. Consider a function
a() that calls setjmp() and then invokes b(). b()
allocates some memory, opens a file, loads data from
the file into the allocated memory, and calls c() to
operate on the memory. Depending on the value returned
by c(), b() either loads the next batch of data and calls
c() again or else closes the file, frees the memory, and
returns to a().

Unfortunately, c() calls longjmp() and skips straight
back to a() without giving b() a chance to clean up. The
memory remains allocated and the file remains open, and
since this is contrary to the expected behavior of a b()
call there may well be trouble. That's the principal
drawback: longjmp() leaps from a point deep in the call
stack straight back to the setjmp() caller, and doesn't
give the intervening functions any chance to put their
affairs in order.

Now, it is certainly possible to build a more elaborate
mechanism atop basic and simple longjmp(). One can also
exercise ferocious discipline to avoid writing a b() that
calls a possibly-longjmp()ing c() while still in a state
that requires cleanup. Both approaches require extra work
since the language itself offers no help; both approaches
are viable but not as basic and simple as longjmp() itself.
Is longjmp() used for anything other than error/exception handling?


Various people have tried to build a kind of coroutine
linkage out of it, but I haven't yet seen one that looked
much good: They all seem to involve longjmp()ing back into
a function that has already returned, perhaps by a longjmp()
of its own. Cooperative multi-threading schemes appear to
rely on the same sort of abuse. (I have not, of course, seen
everything.)

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 12 '05 #125
"Malcolm" <re*******@btinternet.com> wrote in message
news:dn**********@nwrdmz02.dmz.ncs.ea.ibs-infra.bt.com...
"P.J. Plauger" <pj*@dinkumware.com> wrote

Wait, is Java a modern language superior to C, or is it still
going through growing pains?
I think it is both. It is a much better OO language than C++, since the
designers learnt from the mistakes.
A big advantage over C is that you have automatic memory allocation. No
more messing about with testing mallocs() and then painstaking freeing
your half-built structure on fail, just for a refusal to give you a
hundred bytes that can never happen.
A big disadvantage in relation to C is the automatic memory allocation -
now we can't fine tune the prgoram where we need performance.
I pretty much agree with that assessment.
A popular dialect of
C (never standardized) used far and near pointers, to good
effect, to deal with a practical architectural issue. (They
even proved useful on a couple of non-X86 platforms as well.)
Whatever problems they caused pale compared to the races,
deadlocks, and sheer lack of portability inherent in Java
threading.

All practical C programs use pointers. Most Java programs don't need
threads.


Right. And pointers work right, if you use them right -- even near
and far ones. Whereas Java threads often *appear* to work right,
when you use them right, on one platform then behave pathologically
on another platform. They've even been known to change behavior
between releases of one OS. IMO they're two entirely different
kettles of fish.
What I have never done is written an all-singing, all-dancing Java
interactive application. I just use it for providing a simple graphical
UI. I would prefer C, but there is no standard windowing library that all
platforms (with appropriate hardware) are guaranteed to support.
Again, I agree that's a good use for Java instead of C.
This would be a trivial job - just define half a dozen function to open a
window, close it, draw a pixel, query the mouse position, and synchronise
the screen. However no-one has done so, and it is non-trival to implement
such an interface given another a high-level interface.
I've seen several implementations of just such an interface,
callable from C. The problem is that you need another layer or
two atop this set of primitives to get anything done. And IMO
this is still an experiment in process. I've played a bit with
X, Qt, and the first couple of generations of Java. (The fact
that Java is on its third or fourth GUI tells you something
about the state of the art.) All of these are find for drawing
simple screens, but all show surprising variations in screen
appearance across different platforms.

Yes, I kinda wish Standard C came with at least a simple
graphics package. I'd use it to produce simple graphic
displays. But I'm not sorry that the C and C++ standards
committees have shied away from this area -- both have plenty
of work to do with a more certain payoff.
Java indeed "solved" a number of problems that C never has,
like flexible types and arithmetic representations. C hasn't
solved them because some of understand that they're not
problems.

It depends what you are doing, Java aims for rigorous portability - the
same program produces the same output, regardless of platform. Obviously,
we would chose this, other things being equal.
C aims for the next level of portability - the same program produces
correct output, regardless of platform.
So let's say my task is to load in a model of a molecule, rotate it given
user angles, and then output the result as a JPEG image. If the patron
specifies that the JPEG file must be, byte for byte, exactly the same on
every platform, then Java is the language to go for. There might be good
reasons for demanding this - for instance, you can test the program
automatically. Normally, however, the patron is happy with an image that
he can view, and shows the molecule in the orientation he entered.


I mostly agree with your representation of the goals of Java and C.
I don't agree with the degree to which Java has succeeded or C
has failed, at least in the context of your example.
Right. And that's exactly what you do with *every* program
that purports to be portable in the real world. Try telling
a project manager, "Don't bother to test the Java (or Perl,
or whatever) components before shipping -- they're guaranteed
to work on all supported platforms." Uh huh.

But this is an unacceptable situation, which we must work to change.


You may find it unacceptable, but I don't expect it to change
in (what's left of) my lifetime. That's just good engineering
practice. We can work to lower the *cost* of testing, but test
we must.
An
engineer working for a bolt factory expects to have to test his bolts for
stress, manufacturing tolerances, or whatever. The engineer building a
bridge expects to order the bolts, and for them to do what it says on the
box. That's the way it should be with software.


And it is, to the extent that the behavior of software in
a large system has no greater impact than, say, a failing
bolt, it's testing is separable and isolated.
I agree that writing portable code takes effort, which is
why I often advise people not to aim for portability unless
they're really sure they'll actually do one or more ports.
Otherwise, you'll never recoup the investment. I simply
observe that when I do choose to invest in portable C code,
the extra cost is not that great for the reward in extra
usability/marketability.

I think a common mistake is to suppose that the main benefit in writing
portbale code is to be able to compile and run it on a different platform.
It sounds commonsensical. In fact, by making code portable, you improve
the logical structure of your program, making it more readable, and less
likely to contain errors. That is often a much greater benefit.


Sometimes that's true. Sometimes you have to expend extra
effort, as I said above. I agree that the *habits* that
help you write portable code also benefit non-portable
code. I like to believe that's what you meant.
Probably written in C, and callable from C. So you think a
programming language has to ship with a huge library to call
itself portable? I don't.

I don't know about that one. I use Java for trivial GUI apps, precisely
because C has no library. I would prefer to keep all my code in the same
language.


Again I agree. But I can assure you that, as both a consumer
and producer of standard libraries, bigger is *not* necessarily
better. IME, it's almost always worse.
auto-serialized
data structures, threading, built-in array/string safety and memory
leak protection and so on.


All of those are nice, and all of them are available in most of
the C compilers I use. Requiring them to be in the standard
library shipped with a language translator is, however, a
two-edged sword.

With most of these things, you have to choose between them and pointers.
It is easy enough to serialise a data structure, as long as it has no
pointers. It is a bit harder to provide threading, but a lot harder still
if you cannot protect memory. Same for arrays and memory leaks.
C is the language of pointers.


Yes it is, and I don't take that as axiomatically bad/dangerous/
inconvenient/whatever as you seem to. C++ has references, which
are effectively secret, read-only, guaranteed initialized
pointers; but you can subvert them too and cause really hard
bugs to find. Java and other OO languages have handles, which
are even more tightly managed than references, but they too
have their problems -- memory leaks, uncertain object lifetimes,
etc. Eliminating pointers is neither necessary nor sufficient
to improving code reliability IMO/IME.
Excuse me, but you made two statements about things that go on
inside my head. And you happen to be wrong. You're defending them
by stating opinions that come from inside *your* head. And I
happen to believe most of those opinions are not supported in
the real world. I am undisputably the world's foremost authority

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
on what goes on inside my head. You seem to have problems

^^^^^^^^^^^^^^^^^^^^^^^^
distinguishing my reality from your personal reality from the
real world we both inhabit. I try not to.

How do you know you are not suffering from a mental illness?


<OT>Good point. You will notice that I distinguish my internal
reality from the real world -- that's an important self check.
But even if I'm a four-door nutcase, I *still* know more about
what's inside my head than others, who have to use indirect
means. And I deeply resent anybody telling me what I think
or feel, particularly someone with a weak grip on logic and
fuzzy boundaries between different views of reality.</OT>
In posts leading up to this one,
you've mentioned Fortran and Pascal -- this is in a response to my
statements about "modern languages in common use".


Right. But that's not the *only* thing I've said, by a
long shot. Your syllogisms are once again bass-ackwards.

I'm using Fortran 77. When I started my new position, everyone was using
it, because it was the standard for academic programming. I decided to put
IO and memory allocation into C, and keep the numerical part of the
program in Fortran - I think it was the right decision but two months into
starting, all we've really achieved is to convert existing assets from
Fortran 77 to C, so I won't now do the scientific work I had hoped to do
by Christmas.
I'm working now, in December 2005. So for me Fortran 77 is very much still
a modern language.


Indeed it is. Otherwise, C and C++ wouldn't keep working so hard
to lure Fortran programmers.
Sigh. What I said was that you make a Boolean out of a quantity
by using it in a comparison predicate. I used that as an
example of how people can conclude that a program is "not
portable" by performing some sort of implicit or explicit
quantitative estimate. The point is that portability
becomes a Boolean *only* when you apply a predicate to it.

Sure. I'd say that a very important rule is "will this program be usable
if compiled with zero changes to the source?". Even if you need to make a
trivial change, e.g. converting MAX_PATH to _MAX_PATH, you require a
competent programmer, and the value of the source is diminished.
However even this isn't completely Boolean. What about source which
compiles, but on Unix require an "-lm" to be added to the the makefile /
compiler options? This is a similar irritation, but not as bad as the
source change. In a lot of environments, the rule will be "OK, the source
has changed, now please rerun all the test suites", but not if a compiler
flag changes.


You're describing various implicit costs in moving even a
"completely portable" program to another platform. That's
why the dictionary definition is so lame -- it describes
a Platonic ideal with next to no practical significance.
But the problems, in the case, *came* from C, the language it was
implemented in. Once its up and running, presumably, he'll have the
portable Perl language ready for him to use.


Other people have challenged your presumption better than I can.

When I use Perl, I usally use it for tasks that are not portable, because
it ships as source and hacking into a perl script is less intimidating
than recompiling C source. So if you want to load a thousand models from
/freddy/models, all starting with "att" and with digits between 0-52 as
suffixes, Perl is ideal. The task is, of course, very much dependent on
the needs of the moment.


Exactly. Our little shop does an incredible amount of in-house
work with "scripts" in: DOS command, Unix sh, ed, awk, perl,
Visual Basic, Maplesoft, and doubtless several other things
that Chris, Pete, or John has seen fit not to let me find out
about. Our goal is to produce highly portable and reliable:
C, C++, HTML, DOS scripts, and sh scripts. But we try to be
clear, for each of the bits of code we produce, just how
portable/readable/tested it should be.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Dec 12 '05 #126
Netocrat <ne******@dodo.com.au> writes:
On Mon, 12 Dec 2005 02:08:31 +0000, Keith Thompson wrote:
[...]
I'd still rather test for errno!=0 than errno>0. If errno *is*
somehow set to a negative value, it probably indicates an error (in
the code that sets errno if nothing else).


Agreed (2nd sentence) - that's why the code prints "fprintf: unspecified
error" for negative errno's.

[...]

One of these days, I just might consider reading code before
commenting on it. (*sigh*)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 12 '05 #127
On Mon, 12 Dec 2005 01:15:42 +0100, in comp.lang.c , jacob navia
<ja***@jacob.remcomp.fr> wrote:
I assume that if fprintf returns a negative value the disk
is full.
Well, I suspect you could be less assumptive than that

if (fprintf(fp, "foo")< 0)
{
puts("unable to write foo");
puts("possible causes: disk full, disk offline, tape removed");
puts("ion storm near mercury, no more memory etc");
puts("or a suitable list of sensibile possibilities given");
puts("the type of device you're trying to write to"):
puts("Yu decide");
exit(1);
}
switch (err) {
case EOF:
// No space. Erase temp files
break;
default:
// Other errors
}
return err;


The problem I have with this is that there's typically no actual
action the programme can take. There may /be/ no temp files, there may
not be a disk, the "no space" error might arise because the
destination really meant "I'm busy, go away and come back in 5"...

Plus that sort of error handling is deeply icky.

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Dec 12 '05 #128
On 11 Dec 2005 23:40:25 GMT, in comp.lang.c , Chris Torek
<no****@torek.net> wrote:
In article <43***********************@news.wanadoo.fr>
jacob navia <ja***@jacob.remcomp.fr> wrote:
Since ... we have at least 16 bits in an int, we can easily make
up ranges big enough to accomodate for a LOT of error codes, 32767
in fact. The standard would define several ranges, and leave a lot
of logical eror code space unused for the implementations to use.


Please go use VMS for several years. It *does* this. Once you
have experience with how it works (and when and how it fails),
*then* come back and propose putting it into a future C standard.


Gawd how I miss those VMS error codes. It certainly teaches one to
return sensible values from main()...
----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Dec 12 '05 #129
In article <11**********************@g14g2000cwa.googlegroups .com>,
we******@gmail.com writes
pemo wrote:
Is C really portable?


No. The standard embodies a portable syntax which exists as subset of
any compliant compiler, but that's exactly as meaningless as you might
suspect it is. For example, I don't believe there exists any pair of C
compilers from different vendors that have exact source space
compatibility.
[...] And, apologies, but this is possibly a little OT?


Well C.L.C. is a group about ANSI standard C.


No. It is about ISO C

--
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
\/\/\/\/\ Chris Hills Staffs England /\/\/\/\/
/\/\/ ch***@phaedsys.org www.phaedsys.org \/\/\
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Dec 12 '05 #130
Chris Hills <ch***@phaedsys.org> writes:
In article <11**********************@g14g2000cwa.googlegroups .com>,
we******@gmail.com writes
pemo wrote:
Is C really portable?


No. The standard embodies a portable syntax which exists as subset of
any compliant compiler, but that's exactly as meaningless as you might
suspect it is. For example, I don't believe there exists any pair of C
compilers from different vendors that have exact source space
compatibility.
[...] And, apologies, but this is possibly a little OT?


Well C.L.C. is a group about ANSI standard C.


No. It is about ISO C


I might have written "Yes. it is about ISO C".

As everyone here probably knows by now, the original C standard was
issued by ANSI in 1989. ISO adopted it (with some changes like
renumbering the sections) in 1990; ANSI, as the US member of ISO,
adopted the ISO standard. The current standard is the 1999 ISO
standard, which is also recognized by ANSI. (And there have been a
couple of technical corrigenda since then.) I suppose it's debatable
whether C99 can properly be referred to as "ANSI C", but it's not
interestingly debatable.

The term "ANSI C" is used colloquially to refer to the 1989 standard
(the term became popular while the standard was still being developed,
and it stuck). Discussion of the language defined by the 1989 ANSI C
standard is topical here. So, I would say, is discussion of the
pre-ANSI version of the language defined by K&R1, and even earlier
versions from before that.

IMHO, YMMV, HAND.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 13 '05 #131
Chris Hills wrote:
In article <11**********************@g14g2000cwa.googlegroups .com>,
we******@gmail.com writes
pemo wrote:
Is C really portable?


No. The standard embodies a portable syntax which exists as subset of
any compliant compiler, but that's exactly as meaningless as you might
suspect it is. For example, I don't believe there exists any pair of C
compilers from different vendors that have exact source space
compatibility.
[...] And, apologies, but this is possibly a little OT?


Well C.L.C. is a group about ANSI standard C.


No. It is about ISO C


What is that supposed to mean? Are you saying that only the latest
version of C is topical here or that neither verion of the Standard is
correctly referred to as ANSI C? The original standard was created by
ANSI and adopted by ISO, the latest verion was created by ISO and
adopted by ANSI so I don't see your point if that was your argument.

Robert Gamble

Dec 13 '05 #132

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

38
by: Martin Marcher | last post by:
Hi, I've read several questions and often the answer was 'C knows nothing about .' So if C knows that little as some people say, what are the benefits, I mean do other languages know more...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.