Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 11:53 27 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : MMBasic for Windows - betas

     Page 9 of 30    
Author Message
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4243
Posted: 06:38am 10 Mar 2022
Copy link to clipboard 
Print this post

Peter,

The option you give for text. Either in quotes when there is a space in the text, or, without quotes.

Can that option als be applied to all commandline commands.

So

Run demo.bas (without quotes)
Chdir wolf3d
Edit test.bas

Regards,

Volhout
PicomiteVGA PETSCII ROBOTS
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4042
Posted: 10:13am 10 Mar 2022
Copy link to clipboard 
Print this post

Good morning Peter,

You can run, but you can't hide from the power of unit-testing .

1. Here is a doozy:

> list "tick-bug.bas"
Dim t1%, t2%, t3%, t4%

' Comment this out and the ticks are accurate !!!
Pause 1000

SetTick 100, inc_t1, 1
SetTick  50, inc_t2, 2
SetTick  10, inc_t3, 3
SetTick   2, inc_t4, 4

Pause 1000

SetTick 0, inc_t4, 4
SetTick 0, inc_t3, 3
SetTick 0, inc_t2, 2
SetTick 0, inc_t1, 1

Print Str$(t1%); " should be ~10"
Print Str$(t2%); " should be ~20"
Print Str$(t3%); " should be ~100"
Print Str$(t4%); " should be ~500"

Sub inc_t1()
 Inc t1%
End Sub

Sub inc_t2()
 Inc t2%
End Sub

Sub inc_t3()
 Inc t3%
End Sub

Sub inc_t4()
 Inc t4%
End Sub

> run "tick-bug.bas"
18 should be ~10
37 should be ~20
188 should be ~100
681 should be ~500


2. And here's a subtle one, that is probably also present on the CMM2 because I remember fixing it in MMB4L starting with the CMM2 error-handling code:

list "error-bug.bas"                                                                                                        
Print "  ";
On Error Skip 1
Error "foo"
Print "MSG: " Mm.ErrMsg$

> run "error-bug.bas"
 MSG:
Error in line 5: foo


Note how the Mm.ErrMsg$ has "incorrectly" got a leading CRLF. You need to output a CRLF when printing an uncaught error if the cursor is not at the start of the line, but you don't want that CRLF to be in Mm.ErrMsg$ itself, because that's just awkward.

Best wishes,

Tom
Edited 2022-03-10 20:33 by thwill
Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9122
Posted: 11:46am 10 Mar 2022
Copy link to clipboard 
Print this post

MMBasic.zip


Fixes above issues
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 4243
Posted: 09:47pm 10 Mar 2022
Copy link to clipboard 
Print this post

I know some of you already have exploited remote IO for MMB4W.
This is my experiment. I connected a CMM1 through serial port to the laptop running MMB4W in Wine (linux). This is not different from attaching a picomite, but the CMM1 was lying on my desk.

I configured COM2 to link to /dev/ttyACM0 in regedit. The CMM1 enumerates in linux as /dev/ttyACM0

Using the "AUTO" command (MMBasic 4.5 command for AUTOSAVE) and terminating with CTRL-C (CTRL-Z in modern MMBasic) I downloaded a program and run it.

See attached code for MMB4W. The CMM1 does not need pre-programming. It is just a virgin machine with just MMBasic 4.5c

'test if we can remote program mites
'tested with maximite CMM1

'read ADC values from CMM1 in MMB4W

'open communication with the CMM1
open "com2:3800" as #1

'write a program to CMM1 from the data lines
do
 read a$
 if a$="" then a$=chr$(3)  'stop auto(save) mode with ctrl-C
 print #1,a$
 pause 500 'estimated wait between commands
loop until a$="run"

'gather the output of the CMM1 and print on screen
c$=""
do
 if loc(1)<>0 then
   b$=input$(1,#1)
   'convert ascii data separated by <CR> to numeric value
   if b$=chr$(13) then
     print val(c$):c$=""
   else
     c$=c$+b$
   end if
 end if
loop while inkey$=""

'terminate the program
print #1,chr$(3)  'stop running program
pause 1000
close #1
end

'data statements containing the CMM1 program and commands
data "new"  'clear program memory
data "auto" 'enter autosave mode
data "setpin 2,ain:settick 100,intr:do:loop:sub intr:print pin(2):end sub" 'the program
data "" 'this symbolizes the chr$(3)
data "run" 'start the program


I did not know how to put chr$(3) in a data statement, so that is a kind of a "cludge".
Edited 2022-03-11 07:50 by Volhout
PicomiteVGA PETSCII ROBOTS
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4042
Posted: 10:31am 11 Mar 2022
Copy link to clipboard 
Print this post

Good morning Peter, thank you for your continued efforts. You've almost cleared all the errors reported by my unit-tests, though I will need to take another pass to ensure I haven't disabled any of them incorrectly.

1. LOF is not correctly implemented:

> list "lof_bug.bas"
Option Console Both

Dim f$ = "hello_world.txt"

Open f$ For Output As #1
Print #1, "Hello World";

Print Lof(#1)
Close #1

Open f$ For Random As #1
Print Lof(#1)
Close #1

On the CMM2:
> run "lof_bug.bas"
11
11

On MMB4W:
> run "lof_bug.bas"
0
0


2. EOF does not know that you've increased the maximum file number from 10 to 128:

> list "eof_error.bas"
Option Console Both
Open "hello_world.txt" For Output As #11
Print #11, "Hello World"
Print Eof(#11)
Close #11

> run "eof_error.bas"
Error in line 4: Invalid file number


3. Also there are some keywords not being highlighted in the editor:
- CMM2: Console, Both & Random
- MMB4W: Both & Random
Edited 2022-03-11 20:32 by thwill
Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 830
Posted: 05:54pm 12 Mar 2022
Copy link to clipboard 
Print this post

When I try to start a program with the name "solarsys480x320.bas" with
MMBASIC 0 "solarsys480x320.bas"
, only follwing happens:



That's all - nothing else happens...

This program is in the same folder as MMBasic.exe "\Documents\MMBASIC"

Frank
 
phil99

Guru

Joined: 11/02/2018
Location: Australia
Posts: 2135
Posted: 03:36am 13 Mar 2022
Copy link to clipboard 
Print this post

The output screen shows that MMBasic is looking in the root directory for the program and not finding it. To test this put a copy of it in "\" or include the path in the command.

MMBASIC 0 "\Documents\MMBASIC\solarsys480x320.bas"

If you want that to be the default path type:-

OPTION DEFAULT PATH "\Documents\MMBASIC"

or if you wish to keep the current default path:-

OPTION SEARCH PATH "\Documents\MMBASIC"

To see what the current default path is type:-

OPTION LIST
.
Edited 2022-03-13 13:42 by phil99
 
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 830
Posted: 07:35pm 13 Mar 2022
Copy link to clipboard 
Print this post

@Phill99:
THANKS! This helps a little bit...

This is my business PC and there is a problem with the username - it is created there with a space in between.     This has the consequence that the paths are often not recognized correctly...  

Let's see if I can't bend the path completely...

Frank
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6099
Posted: 08:49pm 13 Mar 2022
Copy link to clipboard 
Print this post

A space in the default path is not a problem.
Just start from "C:\" and enclose it in quotes when specifying.



Seems to work for me...

Jim

Edit:  If you have any Unicode characters in the path there could be problems.
Edited 2022-03-14 07:02 by TassyJim
VK7JH
MMedit   MMBasic Help
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9122
Posted: 09:34am 14 Mar 2022
Copy link to clipboard 
Print this post

Tom

I've fixed the two issues you found - both trivial.

HOWEVER.....

Option Console Both
Open "hello_world.txt" For Output As #11
Print #11, "Hello World"
Print Eof(#11)
Close #11


On the CMM2 this gives 1
On MMB4W this give 0

If I change the code to fgetc 2 chars and ungetc them then I still don't see eof. It appears that feof is not useful when a file is open for write rather than read. What does MMB4L do? What is your implementation for MMfeof and or fun_eof ?
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4042
Posted: 10:08am 14 Mar 2022
Copy link to clipboard 
Print this post

Hi Peter,

  matherp said  What does MMB4L do? What is your implementation for MMfeof and or fun_eof ?


I'd never tried calling Eof(#filedes) on a file I am writing before ;-)

The answer is that MMB4L reports the system error "Bad file descriptor".

The implementation looks like:
int file_eof(int fnbr) {
   if (fnbr < 0 || fnbr > MAXOPENFILES) ERROR_INVALID_FILE_NUMBER;
   if (fnbr == 0) return 0;

   switch (file_table[fnbr].type) {
       case fet_closed:
           ERROR_NOT_OPEN;
           break;

       case fet_file: {
           FILE *f = file_table[fnbr].file_ptr;
           errno = 0;
           int ch = fgetc(f);  // the Watcom compiler will only set eof after
                                // it has tried to read beyond the end of file
           error_check();
           int i = (feof(f) != 0) ? 1 : 0;
           error_check();
           ungetc(ch, f);  // undo the Watcom bug fix
           error_check();
           return i;
       }

       case fet_serial:
           return serial_eof(fnbr);
   }

   ERROR_INTERNAL_FAULT;
   return 1;
}


But as you can see by the comment about the Watcom compiler this is just a rearranged version of Geoff's MMBasic for DOS/Windows code that I haven't dug into yet.

The error is coming from trying to call fgetc() on a write-only stream, which I guess isn't that surprising.

A straight call to the POSIX feof(f) function returns 0 which is what I would expect as no operation is being performed that sets that flag on the file-descriptor.

Perhaps the CMM2 is wrong ? Or you should just hard-code Eof(#filedes) to return 1 when called on a write-only steam if that is what you think the behaviour should be ?

I'm sorry that I don't have time for more investigation today, I slept poorly and need to go and do something about that.

Best wishes,

Tom
Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9122
Posted: 10:33am 14 Mar 2022
Copy link to clipboard 
Print this post

More info FYI

It works when the file is open for random IFF you fflush before the fgetc. It always returns 0 when the file is open for write
 
Plasmamac

Guru

Joined: 31/01/2019
Location: Germany
Posts: 554
Posted: 02:52pm 14 Mar 2022
Copy link to clipboard 
Print this post

Open "hello_world.txt" For Output As #11
Print #11, "Hello World"
Print Eof(#11)
Close #11


blitz3d     shows 1,1
Blitzplus   shows 1,0
Glbasic     shows 1,1
qb64        shows 0,0



'Blitz3d and Blitzplus

fileout = WriteFile("hello_dworld.txt")
DebugLog Eof(fileout); eof
WriteString( fileout, "MM4BW" )
DebugLog Eof(fileout); eof ?
WaitKey()

'glbasic  debug on

OPENFILE(1, "EOF.txt", FALSE)
DEBUG ENDOFFILE(1)
WRITELONG 1, 1234
DEBUG ENDOFFILE(1)
CLOSEFILE 1
SLEEP 2222


'  qb64
Open "EOFqb64.txt" For Output As #1
Print EOF(1)
Print #1, x, y, z$
Print EOF(1)
Close #1
Print "File created with data. Press a key!"
K$ = Input$(1) 'press a key





Plasma
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3802
Posted: 03:01pm 14 Mar 2022
Copy link to clipboard 
Print this post

  matherp said  If I change the code to fgetc 2 chars and ungetc them ...

Only one ungetc at a time is guaranteed to work so for portability don't do two or more.

John
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6099
Posted: 08:37pm 14 Mar 2022
Copy link to clipboard 
Print this post

Just to add to the list
PureBasic:
If CreateFile(0, "hello_world.txt" )
  Debug Lof(0)
  Debug Eof(0)
  Debug Loc(0)
  Debug ""
 WriteString(0,"Hello World",#PB_Ascii)
 Debug Lof(0)
 Debug Eof(0)
 Debug Loc(0)
 CloseFile(0)
EndIf


Eof() >> 1,1
Loc() And Lof() >> 0,11

Jim
VK7JH
MMedit   MMBasic Help
 
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 830
Posted: 07:58am 15 Mar 2022
Copy link to clipboard 
Print this post

@TassyJim:

It seems to be something different when the space is in the username...
Anyway - I moved everything to D: and adjusted path - now it works!  

Frank
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4042
Posted: 11:19am 15 Mar 2022
Copy link to clipboard 
Print this post

More on the EOF question:

Consider this "C" code:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
   errno = 0;
   FILE *f = fopen("hello-world.txt", "w");
   if (!f) perror("fopen() error");
   fprintf(f, "Hello World");
   printf("feof before flush = %d\n", feof(f));
   if (fflush(f) != 0) perror("fflush() error");
   printf("feof after flush = %d\n", feof(f));
   int ch = fgetc(f);
   if (ch == EOF) {
       printf("feof after fgetc = %d\n", feof(f));
       printf("ferror() = %d\n", ferror(f));
       printf("errno = %d\n", errno);
       if (ferror(f)) {
           perror("fgetc() error");
           exit(0);
       }
   } else {
       printf("OK\n");
   }
   if (fclose(f) != 0) perror("fclose() error");
}


Compiled and run on Windows 10:
thwill@PSEUK1383 MINGW64 /c/home-thwill
$ cl c-file-io.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.14.26433 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

c-file-io.c
Microsoft (R) Incremental Linker Version 14.14.26433.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:c-file-io.exe
c-file-io.obj

thwill@PSEUK1383 MINGW64 /c/home-thwill
$ ./c-file-io.exe
fgetc() error: No error
feof before flush = 0
feof after flush = 0
feof after fgetc = 0
ferror() = 1
errno = 0


Compiled and run on Linux:
thwill@pseuk1383:~/home-thwill$ gcc --version
gcc (Ubuntu 11.2.0-7ubuntu2) 11.2.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

thwill@pseuk1383:~/home-thwill$ gcc c-file-io.c
thwill@pseuk1383:~/home-thwill$ ./a.out
feof before flush = 0
feof after flush = 0
feof after fgetc = 0
ferror() = 1
errno = 9
fgetc() error: Bad file descriptor


In my opinion the Microsoft compiler is a borked in that after calling fgetc() on a write only stream it sets the error flag but doesn't set errno - this is why MMB4W isn't reporting an error because its error handling code for stdio operations ONLY CHECKS errno - this is not C standard compliant; you are supposed to check the return value from the function before consulting the errno because a function that succeeds is according to the C standard still allowed to set errno. MMB4L (currently) has the same non-compliant error handling, but because Linux sets the errno in this case it works and reports "Bad file descriptor".

Note that MMB4W and MMB4L are both basically using the same old code from MMBasic for DOS:
int MMfeof(int fnbr) {
 int i, c;
 if(fnbr < 0 || fnbr > 10) error("Invalid file number");
 if(fnbr == 0) return 0;
 fnbr--;
 if(MMComPtr[fnbr] != NULL) return SerialEOF(MMComPtr[fnbr]);
 if(MMFilePtr[fnbr] == NULL) error("File number is not open");
 errno = 0;
 c = fgetc(MMFilePtr[fnbr]); // the Watcom compiler will only set eof after it has tried to read beyond the end of file
 if(ErrorCheck()) return 0;
 i = (feof(MMFilePtr[fnbr]) != 0) ? -1 : 0;
 if(ErrorCheck()) return 0;
 ungetc(c, MMFilePtr[fnbr]); // undo the Watcom bug fix
 ErrorCheck();
 return i;
}


I think the comment in this code about the Watcom compiler having a bug is spurious. feof(f) does not check if you are at the end of stream 'f', it checks whether the EOF flag has been set on that stream, and in order for that flag to have been set you need to have performed an operation on the stream that generates that condition (e.g. read beyond the end of the stream). Hence the fgetc/ungetc are in general necessary and not something to do with the Watcom compiler. It *might* be possible for the code to provide a short-circuit check to see if feof(f) != 0 is already true before doing fgetc/ungetc ... however if something is writing the file whilst MMBasic is reading it then that will produce the wrong result.

With resepct to MMBasic I think you just need to decide whether EOF called on a file opened FOR INPUT should return 0, 1 or throw an error and then hard-code that in rather than relying on calling feof(). Personally I'm in favour of reporting an error in this case.

Best wishes,

Tom
Edited 2022-03-15 21:27 by thwill
Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9122
Posted: 11:26am 15 Mar 2022
Copy link to clipboard 
Print this post

I'm going to leave it as it now is:

eof on a file open for write reports 0
eof on a file open fro random reports correctly (but note only if you fflush before the fgetc)
eof on a file open for read also works correctly of course.

CMM2 will be different but this is irrelevant because you shouldn't be testing eof on a file open for write in the first place
 
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4042
Posted: 11:31am 15 Mar 2022
Copy link to clipboard 
Print this post

  matherp said  I'm going to leave it as it now is:

eof on a file open for write reports 0


OK, but note that is happening *accidentally* because the error handling for the call to fgetc() is not standards compliant (based on the MMB4W code currently visible on GitHub).

Best wishes,

Tom
Edited 2022-03-15 21:31 by thwill
Game*Mite, CMM2 Welcome Tape, Creaky old text adventures
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9122
Posted: 09:09am 18 Mar 2022
Copy link to clipboard 
Print this post

V5.07.03b7


MMBasic.zip

Fixes the LOF and EOF issues identified above. Note the previous version of LOF returned the number of bytes from the current file pointer to the end of the file - actually probably more useful than the new version which matches the manual and just returns the filesize. Anyone think I should revert?
 
     Page 9 of 30    
Print this page
© JAQ Software 2024