From: wsj@triton.mti.sgi.com (Bill Johnson)
Newsgroups: comp.sys.sgi
Subject: Re: FILE *yyin=stdin; not ANSI-C??
Date: 9 Oct 92 03:39:05 GMT
Reply-To: wsj@mti.sgi.com
Organization: Silicon Graphics, Inc.

In article <1992Oct8.221026.7999@utwente.nl>, emmerik@utrcu1.civ.utwente.nl (Emmerik P.J.L. van) writes:
|> The following looks to me perfectly legal ANSI-C code.
|> 
|> sgi-cad> cat test.c
|> # include <stdio.h>
|> FILE *yyin = {stdin}, *yyout = {stdout};
|> main()
|> {
|> }
|> 
|> Nevertheless i get the following results when compiling on a
|> Silicon Graphics workstation:
|> 
|> sgi-cad> cc -cckr test.c
|> sgi-cad> cc -ansi test.c
|> accom: Error: test.c, line 2: integer constant expected
|>        FILE *yyin = {   (__stdin) }, *yyout = { (__stdout) };
|>        ---------------------------^
|> sgi-cad> cc -xansi test.c
|> sgi-cad> cc -ansiposix test.c
|> accom: Error: test.c, line 2: integer constant expected
|>        FILE *yyin = {   (__stdin) }, *yyout = { (__stdout) };
|>        ---------------------------^
|> 
|> Who is wrong, me or the SGI C-compiler?
|> If i am wrong, how do i initialize a FILE pointer to point to
|> standard input/output.
|> 
|> I am working with version 4.0.1 of the IRIS operating system.

The C compiler is fine.

The problem is that you're assuming that stdin and stdout are constants;
they're not guaranteed to be by the standard.  See ANSI 4.9.1.

A quick look at the pertinent part of stdio.h would have told you what
the problem was:

#if defined(__EXTENSIONS__)
/* the macro versions of _bufend() and _bufsiz() are not allowed in pure ANSI
 * environments as their replacements contain identifiers which are not
 * reserved in all contexts.
 */
#define _bufend(p)      _bufendtab[(p)->_file]
#define _bufsiz(p)      (_bufend(p) - (p)->_base)
/* in impure environments we can use macro replacements with _iob as well */
#define stdin           (&_iob[0])
#define stdout          (&_iob[1])
#define stderr          (&_iob[2])
#else /* __EXTENSIONS__ */
/* in pure ANSI environments, the identifier _iob cant be used in the
   replacement of stdin, stdout, and stderr.  Special variables have
   been introduced in libc which have been initialized appropriately.
   (e.g., __stdin has been initialized with the value &_iob[0])
*/
extern FILE *__stdin, *__stdout, *__stderr;
#define stdin           (__stdin)
#define stdout          (__stdout)
#define stderr          (__stderr)
#endif /* __EXTENSIONS__ */

If you use cc -v -ansi, you can see that __EXTENSIONS__ is not defined
(as it can't be in strict ANSI mode).  cc with no options defaults to -xansi
(extended ANSI); your example will then compile fine in this mode (as
you discovered), as __EXTENSIONS__ is defined.  This is discussed in
the cc(1) man page.

In summary: to initialize a global FILE pointer to point to standard
input/output, you either use -xansi, or do a run-time assignment.
Initializations of automatic variables, of course, will work just fine in
either mode.

-- 
Bill Johnson                   10U-178                   wsj@mti.sgi.com
Silicon Graphics, Inc.                             Office:(415) 390-4283
MTI Compilers                                         Fax:(415) 969-2314
Newsgroups: comp.sys.sgi