[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference hydra::amiga_v1

Title:AMIGA NOTES
Notice:Join us in the *NEW* conference - HYDRA::AMIGA_V2
Moderator:HYDRA::MOORE
Created:Sat Apr 26 1986
Last Modified:Wed Feb 05 1992
Last Successful Update:Fri Jun 06 1997
Number of topics:5378
Total number of notes:38326

1911.0. "Lattice C question (V5.0)" by MSBIS1::LANDINGHAM (Guy M.,BXB1-1/F11,293-5297) Sun Nov 27 1988 13:13

Has anyone tried Level 1 file I/O yet?

I can't figure out why the following doesn't work:

#include <fcntl.h>
... (more code)
int ifh;
char ifname[32];
...
strcpy(ifname, "myfile"); /* myfile is an existing file */

if (ifh = open(ifname, O_RDONLY) == -1) { /* this works: if clause executed */
  /* print failure message */             /* only when file doesn't exist in */
}                                         /* current directory */
...
rdcount = read(ifh, *mybuf, BUFLEN);
...

What happens is that the open() function always returns a 0, which is defined
as stdin, I assume.  If I run this with cpr, I can see that the variable ifh
is always 0 after the call, and the program won't go beyond the first read()
call until I type a character and <RETURN> in the invoking CLI window, which
tells me it's reading from stdin.

Anyone have a clue as to what's going on here?
T.RTitleUserPersonal
Name
DateLines
1911.1Check the operator precedenceLEDDEV::WALLACEMon Nov 28 1988 16:268
    You need parens around the open(...)==-1 part of the expression,
    ie:	if (ifh = (open(ifname, O_RDONLY) == -1) ) {
    
    What happens with the original code is that the compiler first evalutes
    open(...)==-1 and gets FALSE (ie:0) when the file exists. The compiler
    then assigns this value (0) to ifh.
    
    	Ray
1911.2Sorry for the confusionLEDDEV::WALLACEMon Nov 28 1988 16:3013
    WRONG! .1's explanation of the problem is correct but his solution
    is wrong (NOTE: .1 is me :-)).
    
    I guess I type faster than I think, sorry.  The first paragraph
    should have read:
        You need parens around the ifh=open(...) part of the expression,
        ie:	if( (ifh = open(ifname, O_RDONLY)) == -1 ) {
    
    The first paragraph in .1 actualy showed how the compiler was
    evaluating your code.
    
    	Ray
    
1911.3ThanksMSBIS2::LANDINGHAMGuy M.,BXB1-1/F11,293-5297Mon Nov 28 1988 16:3912
    Guess I'm confused about the order of expression evaluation.  In:
    
     (ifh = open(ifname, O_RDONLY) == -1)
    
    I thought that the assignment would be done first, then the comparison;
    come to think of it, why would everyone then go to the bother of
    including the extra parentheses in:
    
      ((ifh = open(ifname, O_RDONLY)) = -1)
    
    ...whose form I've seen hundreds of times in various programs. 
    Temporary (hopefully) insanity on my part.  Thanks very much!
1911.4TLE::RMEYERSRandy MeyersMon Nov 28 1988 20:2755
Re: .3

C supports the idea of logical expressions as in

	flag = x != b;

Test x against b, and assign the truth value to the variable flag.

C's operator precedence is in agreement with most languages here:

	FLAG = X .NE. B		(FORTRAN)
	FLAG = X <> b		(Basic)

and so on for Algol, PL/I, Ada, ...


>      ((ifh = open(ifname, O_RDONLY)) = -1)
>    
>    ...whose form I've seen hundreds of times in various programs. 

I hope that you meant

      ((ifh = open(ifname, O_RDONLY)) == -1)

				      ^- note double =

what you wrote is a semantic error since an assignment expression
can not be a lvalue.  Note that a multiple assignment:

	x = y = z;

is evaluated as

	x = (y = z);

not as the erroneous

	(x = y) = z;


Extra credit:

Why does C use "==" as the test-for-equality operator instead of
"=" like PL/I?

Because C learned something from PL/I's mistakes.  A common PL/I
mistake is to write "x = y = z;" for a multiple assignment.  The
PL/I compiler interprets the second "=" as a relational operator,
and thus tests y against z and assigns the truth value to x.
Furthermore, since PL/I has automatic conversions from any data type
to any other, PL/I will manage to convert the truth value to x's data
type no matter how wild it might be: integer, floating point,
string, ...

Basic has a similar problem.
1911.5VTHRAX::KIPTue Nov 29 1988 03:344
    Yes, the second "=" was a typo, I meant "=="
    just before the -1.
    
    Thanks for all of the information.
1911.6don't understand Lattice vs AmigaDOSJFRSON::OSBORNEBlade WalkerTue Nov 29 1988 11:3437
>#include <fcntl.h>
>int ifh;

>if (ifh = open(ifname, O_RDONLY) == -1) { /* this works: if clause executed */
>  /* print failure message */             /* only when file doesn't exist in */
>}                                         /* current directory */
>rdcount = read(ifh, *mybuf, BUFLEN);
-------------------------------------------------------------------------------
I don't have Lattice C, but I was really puzzled by the example, when I
compare it to AmigaDOS commands. Can someone who knows the Lattice help
a bit:

The open command (AmigaDOS) is
fh = Open(filename,open_mode);
struct FileHandle *fh;
char *filename;
long open_mode; (?) I think- I use MODE_OLDFILE, e.g.

Question is: if an open returns an int, where is the FileHandle structure?
If "nowhere", how do subsequent references to this file know what it is?
Is "ifh" (as above) an offset into a table of FileHandle pointers, which
would explain why it returns "0"?

The AmigaDOS read is
rdcount = Read(fh,in_buffer,BUFLEN);
struct FileHandle *fh;
char in_buffer[BUFLEN];

So, in AmigaDOS, when doing a read, you pass the address of the input buffer,
but the syntax above seems to indicate passing the contents of "mybuf" to 
the read. What is the definition of "mybuf"? 

Sorry if these questions seem dumb, I just don't understand Lattice's change
in the syntax here.

Thanks
John O.
1911.7Different functionsVTHRAX::KIPTue Nov 29 1988 13:5918
    There is a big difference between Open() and open().  The former
    is the "internal" AmigaDOS file open function, while the latter
    is Lattice's own.  Since they are totally distinct functions (which
    consist of distinct code), the only thing they necessarily have
    in common is that they both open AmigaDOS files.
    
    Same is true for Read() and read().
    
    open() and read() are described in the Lattice C Compiler
    documentation.  These are "Level 1" I/O functions (the implication is
    low-level, i.e. not as fancy, faster?).  Lattice also supplies
    equivalent "Level 2" I/O functions fopen() and fread().  I believe the
    fopen() function also returns a FileHandle structure, as does Open().
    
    P.S. I guess I forgot to include the definition of mybuf in my original
    question.  The intent, of course, is to pass the address of the mybuf
    array to fread(). 
1911.8It's all magic :-)LEDDEV::WALLACETue Nov 29 1988 15:076
    >>Question is: if an open returns an int, where is the FileHandle structure?
    The int returned by an open() call is an index into an array of
    "file structures". The array of structures is defined as part of
    the library, not in the application.
    
    	Ray
1911.9open and OpenTLE::RMEYERSRandy MeyersTue Nov 29 1988 19:0929
Re: .6, .7, ,8

.7 and .8 are right here.  It's worth noting that open/read/write are
traditional Unix/C functions.  You will find them in VAX C and Unix C.
Lattice sort of got open wrong though: the Unix and VAX C open takes
three arguments.

For those interested, open, read, and write are not part of the ANSI C
standard.  They were considered too low level and system dependent to
be standardized.


Re: Open's return value

The AmigaDOS function Open does not return a struct FileHandle.  It returns
a file handle, which is the DOS book's short hand for a BPTR to a struct
FileHandle.  In other words, the return value from Open can be shift left
2 bits and then used as a pointer to a struct FileHandle.

struct FileHandle is defined in <libraries/dos.h>.  A related file of
DOS information is <libraries/dosextens.h> (for DOS "extensions").

Likewise, the Lock function returns a BPTR to a struct FileLock (defined
in <libraries/dos.h>).

The buffer argument to Read is a pointer to a memory buffer (usually
an array of char).  The contents of the buffer need no be defined before
calling Read.  Read doesn't look at the buffer: it does stores stuff into
it.
1911.10AmigaDos function usageSSDEVO::YESSEComputing at 6200 ft.Sat Dec 30 1989 22:4421
	Bear with me, I'm rather new to using Lattice (5.04). Having
	read the existing 1911.* notes, I still am missing a few points:

	- Peck's Programmer's Guide shows a simple program on pg. 17,
	  which uses the AmigaDos Open(). It proceeds to make the call:
	  fprintf (dos_fh, ...)  and notes this as an  /* amiga.lib func */.
	  I've tried to run this, with standard linking and linking with
	  amiga.lib before lc.lib, but to no avail...Amy crashes every time.
	  (This makes sense in that fprintf normally accepts a file pointer,
	  as opposed to a FileHandle...is this a misprint, or am I linking
	  to the wrong library? Does fprintf exist in both amiga.lib & lc.lib?)

	- This problem got me to trying to use the oml utility to list the
	  functions in amiga.lib, yet when I tried it, it gave me a series
	  of 'unnamed functions' to name. What method, if any, is available
	  to do this? (Yes, I know, buy the ROM Kernel manual... :-)

	Thanks in advance, not only for this but for all the help made
	available in this notesfile...best wishes for the new decade!

	Keith Y.
1911.11Two versions of fprintfTLE::RMEYERSRandy MeyersSun Dec 31 1989 07:0213
Re: .0

Yes, there are two versions of fprintf.  One is the version in LC.LIB
that is the C version of fprintf and takes a FILE * as an argument.
The other version of fprintf is close-to-C but takes an Amiga DOS 
file handle as its first argument and has strange format specifiers
like %lc.

The function in AMIGA.LIB are documented in:

	The Native Developer's Update ("The Autodocs")
	The old Addison-Wesley "Amiga ROM Kernel: Exec" manual
	The new Addison-Wesley "Amiga ROM Kernel: Autodocs and Includes" manual