News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Read input from Console

Started by Andrea Lanza, May 10, 2006, 09:30:24 AM

Previous topic - Next topic

Andrea Lanza

Hello,
sorry for my english, i'm italian...
I use this command to read input from the user:

Stringa: string;
mov(stdin.a_gets(), Stringa);

This example work well if the user write some text on the console.
But if i want to read some input from another program i lost the last character, for example if another program redirect the input to console and write "xboard", i read in the Stringa variable "xboar".
In Visual Basic net for example i simply can write console.writeline(Stringa) to receive the word "xboard".

Anyone can help me?  :bg
Thank's...


Randall Hyde

Quote from: Andrea Lanza on May 10, 2006, 09:30:24 AM
Hello,
sorry for my english, i'm italian...
I use this command to read input from the user:

Stringa: string;
mov(stdin.a_gets(), Stringa);

This example work well if the user write some text on the console.
But if i want to read some input from another program i lost the last character, for example if another program redirect the input to console and write "xboard", i read in the Stringa variable "xboar".
In Visual Basic net for example i simply can write console.writeline(Stringa) to receive the word "xboard".

Anyone can help me?  :bg
Thank's...



I have added this to my list of bugs to check out for the v1.82 release. It may be a few days before I get a chance to look at this as I'm in the middle of a major overhaul of HLA right now (including a lot of testing because the changes are so massive). But I *am* looking into this.
Cheers,
Randy Hyde

Andrea Lanza


Andrea Lanza

Hi,
If I wrote this piece of code my HLA program correctly receive the input from another win32 program:

elsewhere i wrote...

     w.GetStdHandle(-10);
     mov(eax, CanaleIngresso);
     w.GetStdHandle(-11);
     mov(eax, CanaleUscita);

and this routine correctly catch the string "quit" or everything else...

procedure VerificaComandi;
   static(4)
    lBytesRead: dword;
    buffer : byte[1024];
    strings: string[16];
   begin VerificaComandi;
     w.RtlZeroMemory(&buffer,1024);
     w.ReadFile(CanaleIngresso,&buffer,1023,&lBytesRead,NULL);
     if (lBytesRead > 0) then
        str.tokenize2( &buffer, strings, {' ', #10 });
         mov( 0, ebx );
         while( ebx < eax ) do
            str.ieq(strings[ebx*4],"quit");
            if (al) then
               call UscitaProgramma;
              //w.MessageBox(0,strings[ebx*4],"Matilde", w.MB_OK | w.MB_ICONERROR);
            endif;
           strfree( strings[ebx*4] );
           inc( ebx );
         endwhile;
     endif;
   end VerificaComandi;

But... is there a more simple way to do this?
In C++ I wrote:

char S[256];

   gets_s(S, 255);
   if (!strcmp(S, "xboard"))
   {
      i do some work;
   }

and this work fine.
I have some problem with a_gets() and gets(S).

many thank's
Andrea Lanza

Sevag.K

If you want to use the standard library (high level), try one of these


// for single words
forever
stdout.put ("enter command: ");
mov (stdin.a_gets(), s);
breakif (str.ieq (s, "quit"));
str.free (s);
endfor;

str.free (s);

// quit can be anywhere in string
forever
stdout.put ("enter command string: ");
mov (stdin.a_gets(), s);
breakif (str.iindex (s, "quit")<> -1);
str.free (s);
endfor;

        str.free (s);



Andrea Lanza

Thank's but this way don't work.
I must receive command from an external win32 program and this solution works for user input.
I think that the external win32 program send string in another format. Maybe c/c++ strings? Null terminated?
I don't know why i receive the string without the last character for example, the string send is "quit" and with a_gets() i receive "qui".
The piece of code that i previous wrote work, but i looking for a simple way to do this.

Any suggestion?
Thank's
Andrea

Sevag.K

Well, I don't really have a much better solution... if a_gets() doesn't work, there is probably something wrong with the routine which should be reported to Randall Hyde.  I'll also take a look at it when I get the time.

In the meantime, there is a flaw in your program that will inevitably cause it to work incorrectly, also a couple of suggestions.


procedure VerificaComandi;
   static(4)
    lBytesRead: dword;
    buffer : byte[1024];
    strings: string[16];
   begin VerificaComandi;
     w.RtlZeroMemory(&buffer,1024);
     w.ReadFile(CanaleIngresso,&buffer,1023,&lBytesRead,NULL);
     if (lBytesRead > 0) then


RtlZeroMemory is not needed above as ReadFile will copy a zerro-terminated string to the buffer.
Also, readfile returns >0 in eax if it was successful, so you could just write:

if (eax) then ...

Quote
        str.tokenize2( &buffer, strings, {' ', #10 });
         mov( 0, ebx );
         while( ebx < eax ) do
            str.ieq(strings[ebx*4],"quit");
            if (al) then
               call UscitaProgramma;
              //w.MessageBox(0,strings[ebx*4],"Matilde", w.MB_OK | w.MB_ICONERROR);
            endif;
           strfree( strings[ebx*4] );
           inc( ebx );
         endwhile;
     endif;
   end VerificaComandi;

Okay, the bug in this is in the while loop.
You use:
while (ebx < eax) do...

but then, str.eq changes eax into either 0 or 1, which will will mean that your while loop ends after the 1st iteration and the rest of the tokenized strings don't get freed.

fixed while loop:
         while( ebx < eax ) do
            push (eax);  // preserve eax
            str.ieq(strings[ebx*4],"quit");
            if (al) then
               call UscitaProgramma;
              //w.MessageBox(0,strings[ebx*4],"Matilde", w.MB_OK | w.MB_ICONERROR);
            endif;
           strfree( strings[ebx*4] );
           inc( ebx );
           pop (eax);  // restore eax
         endwhile;


Another potential problem: str.tokenize2 expects HLA strings, so it *may* (not certain) malfunction sometime.

Instead of tokenize, you could use str.a_cpyz and str.index combination.


procedure VerificaComandi;
   static(4)
    lBytesRead: dword;
    buffer : byte[1024];
begin VerificaComandi;
     w.ReadFile(CanaleIngresso,&buffer,1023,&lBytesRead,NULL);
     if (eax) then
        str.a_cpyz (&buffer);
        mov (eax, ebx);  // save string here temporarily
        if ( str.index ( ebx, "quit") <> -1 ) then
           call UscitaProgramma;
        endif;
        str.free (ebx); 
  endif;
end VerificaComandi;


Not much better, but a little smaller, and also has a limitation.  If the string contains "quitit", UscitaProgramma will still be called.




Andrea Lanza

 :U Thank you very much for your suggestion.
Now the code is more readable and i will use it for my program.

Andrea Lanza