[comp.sys.amiga.tech] Excruciatingly simple programming question...

gilmore@vms.macc.wisc.edu (Neil Gilmore) (07/28/90)

This is much simpler than the discussions which normally come up here, 
but the only other Amiga programmer I see regularly doesn't know how to 
do anything other than open a new screen (but at least now he programs 
so that he exits cleanly, though the program grabs the entire system 
while it's running).

What I'm using:

Manx 3.6b? (question on the 'b', not the 3.6)

Amiga 2000, ProRam with 2 megs

1.3 roms, Workbench 34.28(?)

The AmigaDOS Manual (2nd edition)

Programmer's Guide to the Amiga, by Rob Peck.

The problem program (listing 2.2 in Peck) (reproduced here without 
permission):

#include "libraries/dosextens.h"
extren struct FileHandle *Open();

main()
{
   char userinput[256];
   int howmany;
   struct FileHandle *dos_fh;

   dos_fh = Open("CON:10/10/500/150/New Window",MODE_NEWFILE);
   Write(dos_fh,"Please type an input line, then press RETURN\n", 45);
   howmany = Read(dos_fh,userinput,255);
   userinput[howmany] = '\0';
   printf("You typed %ld characters:\n",howmany);
   printf("and here they are:\n");
   printf("%ls\n",userinput);
   Close(dos_fh);
}

Looks simple, huh? Assume that syntax errors you find here are the 
result of my typing, as I get no errors when I compile and link.

The problem:

Open() works fine.

Write() causes the string to be written, but the third arguement 
(length) seems to be ignored, causing endless streams of accented 
characters, screen flashes, and control codes to print. It also causes 
the mouse pointer to cease responding after any click.

When I remove the Write(), the Read() works only if I do not type too 
many characters to the created CON: window. Too many is 'some more' than 
255. Again, length seems to be ignored, but the AD MAnual does not 
explicitly say that only length characters will be read. Typing too many 
characters results in the 'Task Held' requester, and a guru.

After spending much time trying to get this to work, I gave up and tried 
listing 2.2, essentially the same program using a RAW: window. Though 
this program had no Write(), Read() again acted in an unexpected 
fashion. Read() would return after each character typed, presumably 
returning the correct character code, but actualLength was gibberish, 
not 0, 1, -1, or any recognizable number.

There is probably a one sentence explanation for this, perhaps one of 
the differences between Manx and Lattice, but until I can get this sort 
of program to work, there isn't much hope for producing anything useful.

Respond here or by email.

Thank you.

+-----------------------------------------------------------------------+
| Kitakaze Tatsu Raito	Neil Gilmore     internet:gilmore@macc.wisc.edu | 
| Jararvellir,          MACC, UW-Madison bitnet: gilmore@wiscmac3       |  
| Middle Kingdom        Madison, Wi      DoD #00000064 (no ints here)   |
+-----------------------------------------------------------------------+   

a218@mindlink.UUCP (Charlie Gibbs) (07/30/90)

In article <4106@dogie.macc.wisc.edu> gilmore@vms.macc.wisc.edu
(Neil Gilmore) writes:

>What I'm using:
>
>Manx 3.6b? (question on the 'b', not the 3.6)

     Glad to see you got it going.  The Manx 16-bit int default can
bite you if you're not careful.  An alternative solution would be
to change the lines

   Write(dos_fh,"Please type an input line, then press RETURN\n", 45);
   howmany = Read(dos_fh,userinput,255);

to

   Write(dos_fh,"Please type an input line, then press RETURN\n", 45L);
   howmany = Read(dos_fh,userinput,255L);

i.e. explicitly cast those length constants to long, which is what
Write() and Read() are expecting.  In fact, it's probably a good
idea to do it anyway.

     (singing) Portability forever...  :-)

Charlie_Gibbs@mindlink.UUCP
If your nose runs and your feet smell, you're built upside-down.

markv@kuhub.cc.ukans.edu (08/01/90)

In article <4106@dogie.macc.wisc.edu>, gilmore@vms.macc.wisc.edu (Neil Gilmore) writes:
> This is much simpler than the discussions which normally come up here, 
> but the only other Amiga programmer I see regularly doesn't know how to 
> do anything other than open a new screen (but at least now he programs 
> so that he exits cleanly, though the program grabs the entire system 
> while it's running).
> 
> What I'm using:
> 
> Manx 3.6b? (question on the 'b', not the 3.6)

I think this is the problem.

> #include "libraries/dosextens.h"

This is the only include.  No prototypes (of course being a Lattice
person I don't even know if Manx 3.6x supports them).  However...

> extren struct FileHandle *Open();
> 
> main()
> {
>    char userinput[256];

>    Write(dos_fh,"Please type an input line, then press RETURN\n", 45);

In Manx, ints (and unnamed integer quantities) default to 16 bits.  If
memory serves me write (sorry, bad pun), most DOS functions expect 32
bit numbers (so you can do BIG reads and writes in one shot).  If you 
execute this function call and Manx defaults to short ints, you will
get a 16 bit representation of 45 pushed on the stack.  The stub in
amiga.lib will will pull of what it expects to be a 32 bit int, which
means you will get 16 bits of random garbage (which is guarenteed to
create a number a lot bigger than 45).

The solution is to use prototypes or casts.  Try including
"exec\types.h" to get the Amiga standard types, and then try
you call like:

  Write(dos_fh,"Please type blah blah blah \n", (ULONG) 45);

Or maybe it should be (LONG), but it shouldn't make a difference here.
The point is your casting it to a 32 bit int which results in a 32 bit
representation  of 45 getting pushed on the stack.

>    howmany = Read(dos_fh,userinput,255);

Same here type (ULONG) 255.
 
> When I remove the Write(), the Read() works only if I do not type too 
> many characters to the created CON: window. Too many is 'some more' than 
> 255. Again, length seems to be ignored, but the AD MAnual does not 
> explicitly say that only length characters will be read. Typing too many 
> characters results in the 'Task Held' requester, and a guru.

AmigaDOS will not overrun the length passed, but since its gettng some
random number (a lot bigger than 255), its' overrunning your buffer
after you type too many charecters.
 
> After spending much time trying to get this to work, I gave up and tried 
> listing 2.2, essentially the same program using a RAW: window. Though 
> this program had no Write(), Read() again acted in an unexpected 
> fashion. Read() would return after each character typed, presumably 
> returning the correct character code, but actualLength was gibberish, 
> not 0, 1, -1, or any recognizable number.

Probably a similar problem.  Read is plugging in a 32 bit value to
your 16 bit int.
 
> There is probably a one sentence explanation for this, perhaps one of 
> the differences between Manx and Lattice, but until I can get this sort 
> of program to work, there isn't much hope for producing anything useful.

Lattice uses 32 bit ints by default (although you can use 16).  Manx
uses 16.  In general either cast everything, or compile with 32 bit
ints (and make you link with 32 bit libs like cl32.lib instead of cl.lib). 

Or upgrade to Manx 5.0 or buy Lattice.  Function prototypes solve this
whole problem if you use them (with lattice I just #include <proto/all.h>
and I have prototypes for every system function.
> 
> Thank you.

Good luck,
-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mark Gooderum			Only...		\    Good Cheer !!!
Academic Computing Services	       ///	  \___________________________
University of Kansas		     ///  /|         __    _
Bix:	  markgood	      \\\  ///  /__| |\/| | | _   /_\  makes it
Bitnet:   MARKV@UKANVAX		\/\/  /    | |  | | |__| /   \ possible...
Internet: markv@kuhub.cc.ukans.edu
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

duncant@mbunix.mitre.org (Thomson) (08/01/90)

This is really a 'C' question more than an amiga question, but I guess that's
how this thread started out anyway...

In article <2667@mindlink.UUCP> a218@mindlink.UUCP (Charlie Gibbs) writes:
>
>i.e. explicitly cast those length constants to long, which is what
>Write() and Read() are expecting.  In fact, it's probably a good
>idea to do it anyway.
>
>     (singing) Portability forever...  :-)

If you've included <stdio.h>, then the compiler should know what kind of
arguments Write() and Read() are expecting, and it should automatically
convert the int to a long int, right?  (I'm assuming that there would be a 
function prototype in the include file.)  Is this a weakness of the Manx
compiler?  By the way, what's the story with Lattice - would it detect/
correct this kind of error?  

Duncan Thomson


--
(Please excuse the typos and garbage caused by line noise.)

duncant@mbunix.mitre.org (Thomson) (08/01/90)

Oops, I just realized that in my last posting on this subject, I 
forgot that |Read() and Write() are not stdio functions, but amiga
functions.  But the same argument follows if the file which 
contained prototypes for Read() and Write() had been included.


Duncan Thomson

--
(Please excuse the typos and garbage caused by line noise.)

a218@mindlink.UUCP (Charlie Gibbs) (08/02/90)

In article <115522@linus.mitre.org> duncant@mbunix.mitre.org
(Duncan Thomson) writes:

>If you've included <stdio.h>, then the compiler should know what kind of
>arguments Write() and Read() are expecting, and it should automatically
>convert the int to a long int, right?  (I'm assuming that there would be a
>function prototype in the include file.)  Is this a weakness of the Manx
>compiler?  By the way, what's the story with Lattice - would it detect/
>correct this kind of error?

     Duh, what's a prototype?  :-)  Seriously, I'm used to working with
ancient compilers that never heard of prototyping, which explains my
meticulous hand-made style.  One of these days I'll have to upgrade to
a newer compiler - hopefully I won't slide into sloppy coding practices.
After that, who knows - maybe even a SOURCE LEVEL DEBUGGER!!!
Wheeeee...

     We Real Programmers must be masochists.  ;-)

Charlie_Gibbs@mindlink.UUCP
I used to be indecisive, but now I'm not so sure.

djh@neuromancer.metaphor.com (Dallas J. Hodgson) (08/03/90)

In article <115524@linus.mitre.org> duncant@mbunix.mitre.org (Thomson) writes:
>Oops, I just realized that in my last posting on this subject, I 
>forgot that |Read() and Write() are not stdio functions, but amiga
>functions.  But the same argument follows if the file which 
>contained prototypes for Read() and Write() had been included.
>
>
>Duncan Thomson
>
>--
>(Please excuse the typos and garbage caused by line noise.)

No, no, no! The purpose of include files is to specify the way arguments
OUGHTTA look, not to COERCE them into something. How would you catch any
lint warnings if, for example, you past a short to an amiga lib function
expecting a 32-bit pointer?

Manx's -l option is wonderful for catching these kind of problems if you
include its <functions.h> file. Compile it using 16-bit ints, then compile
it again using 32-bit ints. Every case where something should be long but
it's not will be identified. The -l stands for 'lint', by the way.

The reason for compiling both ways is because the size of an int may or may
not be the same size as a long, so you may or may not get a warning message.
If you refrain from using ints at all, (explicitly declare shorts & longs)
the only ints use have to worry about are integer constants.

Don't bash something you don't know anything about. Manx is (and ever was)
a fine product.
+----------------------------------------------------------------------------+
| Dallas J. Hodgson               |     "This here's the wattle,             |
| Metaphor Computer Systems       |      It's the emblem of our land.        |
| Mountain View, Ca.              |      You can put it in a bottle,         |
| USENET : djh@metaphor.com       |      You can hold it in your hand."      |
+============================================================================+
| "The views I express are my own, and not necessarily those of my employer" |
+----------------------------------------------------------------------------+

jmelv@madnix.UUCP (John Melvin) (08/08/90)

In article <115524@linus.mitre.org>, duncant@mbunix.mitre.org (Thomson) writes:
> Oops, I just realized that in my last posting on this subject, I 
> forgot that |Read() and Write() are not stdio functions, but amiga
> functions.  But the same argument follows if the file which 
> contained prototypes for Read() and Write() had been included.
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	I didn't catch you first post, but I'll assume you are playing
	with version 3.6.  This version defaults to 16-bit ints (a
	very common source of problems) and doesn't have prototyping.
	Aztec C 5.0x has all the ANSI stuff, prototypes, and a default
	of 32-bit ints so problems are resolved.  Oh, BTW, the Manx
	file you want is "functions.h".
> 
> 
> Duncan Thomson
> 
> --
> (Please excuse the typos and garbage caused by line noise.)


-- 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
John P. Melvin         "Magic is real -- unless declared integer."
                                                                       //
UUCP:  {harvard|rutgers|ucbvax}!uwvax!astroatc!nicmad!madnix!jmelv   \X/ AMIGA