Skip to content

Commit

Permalink
- added NUM function
Browse files Browse the repository at this point in the history
- fixed MAT INPUT so typing in fewer values than needed doesn't raise an error
- MAT INPUT now allows string input
- separated out io routines
  • Loading branch information
maurymarkowitz committed Dec 31, 2024
1 parent 6d1c399 commit 827d1b3
Show file tree
Hide file tree
Showing 12 changed files with 239 additions and 97 deletions.
11 changes: 6 additions & 5 deletions bas/matrix.bas
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
97 Y(0,2)=2
98 MAT PRINT Y
100 DIM B(3,3)
110 REM PRINT"input a 3x3"
120 REM MAT INPUT B
130 REM PRINT"printing input"
140 REM MAT PRINT B
110 PRINT"input a 3x3"
120 MAT INPUT B
130 PRINT"printing input"
140 MAT PRINT B
145 PRINT "number input "NUM
200 DIM C(2,5)
210 PRINT"READing and PRINTing 2x5"
220 MAT READ C
Expand Down Expand Up @@ -104,7 +105,7 @@
5540 PRINT "invert IN to OU"
5550 MAT OU=INV(IN)
5560 MAT PRINT OU
5570 PRINT "the det was "det()
5570 PRINT "the det was "det
10000 DATA 1.5,2.5,3,4,5,6,7,8,9,10
10010 DATA 5,2,0,10
10030 DATA 3,5,2,5
Expand Down
32 changes: 26 additions & 6 deletions doc/RetroBASIC reference manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ RetroBASIC Language Reference Manual

**Copyright © 2023 Maury Markowitz**

Version 2.0.1
Version 2.0.2

[![GPL license](http://img.shields.io/badge/license-GPL-brightgreen.svg)](https://opensource.org/licenses/gpl-license)

Expand Down Expand Up @@ -1802,6 +1802,10 @@ This function returns a string that represents the ASCII representation of the n

This function returns a number of the same value as the number stored as a string, performing the opposite operation of the `STR$` function. For instance, if *sexp* evaluates to "25", this function will return the numerical value 25. `VAL` is generally more common than `STR$` as it is commonly used to convert user inputs into numbers.

#### Variations:

Digital Group BASIC uses `NUM` instead of `VAL` for this functionality. In most dialects, at least those supporing matrix statements, `NUM` returns the number of items typed in a `MAT INPUT` statement. RetroBASIC supports both of these uses of `NUM`, as the matrix version has no parameters while the `VAL`-like version requires a single string parameter.

<!-- TOC --><a name="ucasesexp-and-lcasesexp"></a>
### `UCASE$`(*sexp*) and `LCASE$`(*sexp*)

Expand Down Expand Up @@ -1923,6 +1927,22 @@ Those dialects that allow the program to reserve space in memory for strings, ty

The TRS-80 II and Genie/Color Genie uses `MEM` for this function, while `FRE` returns string space. The Dragon 32 uses `SIZE`.

### `NUM`[(*sexp*)]

`NUM` is a function with two completely different uses.

The main purpose of this function is to return the number of items typed into the last `INPUT` or `MAT INPUT` statement. This was initially introduced in dialects that had matrix support, as it was common for users to enter a blank value in order to stop the `INPUT` statement in the case of large matricies. The program could then use `NUM` to test whether the entire matrix had been filled out, or, for instance, fill out the slots for any non-entered values with zero or some other value.

In RetroBASIC, the functionality of `NUM` has been expanded to also work with conventional `INPUT` statements, as the same issues arise in this case and `NUM` can be just as useful here.

The value of `NUM` is reset at the start of every `INPUT` or `MAT INPUT`, as well as when running a `CLEAR`/`CLR` statement.

The other use of `NUM` is to support the dialect-specific funtion found in Digital Group BASICs, where it is the equivalent of `VAL`. This version will be called if a string expression is provided in *sexp*.

#### Availability:

`NUM` was added in 2.0.2.

<!-- TOC --><a name="peekaexp"></a>
### `PEEK`(*aexp*)

Expand Down Expand Up @@ -2130,14 +2150,18 @@ According to *Illustrating BASIC*, some, or many, versions of MAT PRINT add an e
<!-- TOC --><a name="mat-input-avaravar"></a>
### `MAT INPUT` *avar*[,*avar*,...]]

`MAT INPUT` reads multiple values from the command line, filling the vector or matrix by column and then row. Unlike a normal `INPUT`, no prompt is allowed, and only array variables can be used. Additionally, only numeric values are supported, `MAT INPUT` cannot be used to fill a string array.
`MAT INPUT` reads multiple values from the command line, filling the vector or matrix by column and then row. Unlike a normal `INPUT`, no prompt is allowed, and only array variables can be used.

`MAT INPUT` normally reads a value for every slot in the array, similar to `MAT READ`. However, it parses this data from a single input line, which may not contain enough values to fully populate the array. In this case, no error is reported, and the remaining slots are simply ignored and will contain any value they did before. It sets the pseudo-variable `NUM` to the number of items read, so you can check for this case in code.

*Illustrating BASIC* suggests you should *not* use `MAT INPUT`. This is because the command does not allow a prompt and there is no chance to print anything between each value being input. Worse, there is no way to test the results one-by-one, you will only know there is an issue after all of the values have been typed in and will now have to be re-entered from the start if there is a problem. Using an `INPUT` in a `FOR` loop allows the values to be tested and re-typed individually.

There is also the issue that terminals of the era did not allow you to type more values than could fit on a single line and different implementations offered different solutions to this problem, or none at all. Dartmouth BASIC, for instance, allowed you to type an ampersand to indicate more data would follow on the next line, but this was not universal across implementations. For all of these reasons *Illustrating BASIC* concludes "So for the sake of portability, if nothing else, don't use 'MAT INPUT' for demanding data from the keyboard."

#### See also:

* `NUM`

<!-- TOC --><a name="matrix-operators"></a>
### Matrix operators

Expand Down Expand Up @@ -2217,10 +2241,6 @@ Changes all of the slots in *avar* to 0, or if the optional *aexp*s are provided
120 MAT B=INV(A)
130 IF ABS(DET)<0.01 THEN PRINT "MATRIX INVERSION FAILED"

### `NUM`[(*aexp*)]

`NUM` returns the number of items typed in a `MAT INPUT` statement. It is reset to zero when the program is run or `CLEAR`ed.

<!-- TOC --><a name="error-handling"></a>
## Error handling

Expand Down
5 changes: 3 additions & 2 deletions doc/TODO
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ WB = Wang BASIC
PA = Palo Alto Tiny BASIC
BP - DEC BASIC-PLUS

- add clear_variables and change CLEAR

- word wrap at a given column

- add REDIM?

- EXCHANGE/SWAP that swaps the values of two variables

- MAT INPUT should allow multi-input on a single line, and should set NUM
Digital Group BASIC uses NUM for VAL, but we can do both
- MAT INPUT should allow multi-input on a single line

- LINPUT/LINE INPUT/INPUT LINE

Expand Down
7 changes: 7 additions & 0 deletions doc/VERSIONS
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,10 @@ Major update. See the reference manual for details on the many changes.
Version 2.0.1 - 12 December 2024

Fixing major problems with the GitHub repo. Some very minor changes as well.

Version 2.0.2 - 31 December 2024

- added NUM, which returns the number of items entered in INPUT or MAT INPUT
- MAT INPUT now works with both string and number arrays
- fixed issue in MAT INPUT which raised an error if the input was empty
- separated out input/output routines
2 changes: 1 addition & 1 deletion doc/retrobasic.1
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
.\" License V.2 as specified in the LICENSE file that comes with
.\" the RetroBASIC distribution.

.TH RETROBASIC 1 "20 August 2022" v2.0.1 "RetroBASIC"
.TH RETROBASIC 1 "31 December 2024" v2.0.2 "RetroBASIC"
.LO 1

.SH NAME
Expand Down
70 changes: 70 additions & 0 deletions src/io.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* io (implementation) for RetroBASIC
Copyright (C) 2024 Maury Markowitz
This file is part of RetroBASIC.
RetroBASIC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RetroBASIC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RetroBASIC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */

#include "io.h"

/*
* Waits for a single character. Used for GET.
*/
int getbyte(int fd)
{
int ch;
struct termios old_attrs, new_attrs;
tcgetattr(STDIN_FILENO, &old_attrs);
new_attrs = old_attrs;
new_attrs.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &new_attrs);
system("stty -echo"); //shell out to kill echo
ch = getchar();
system("stty echo");
tcsetattr(STDIN_FILENO, TCSANOW, &old_attrs);
return ch;
}

/*
* Gets a single keystroke, or null if no key is pressed. Used for INKEY$.
*/
int getkey(int fd)
{
#if _WIN32
if (kbhit) {
return getch();
} else {
return 0;
}
#else
int ch;
unsigned char buf[1];
struct termios old_attrs, new_attrs;
tcgetattr(STDIN_FILENO, &old_attrs);
new_attrs = old_attrs;
cfmakeraw(&new_attrs);
new_attrs.c_cc[VMIN] = 0;
new_attrs.c_cc[VTIME] = 0;
new_attrs.c_lflag &= ~(ICANON | ECHO);
// newt.c_cc[VMIN] = 0;
tcsetattr(STDIN_FILENO, TCSANOW, &new_attrs);
ch = (int)read(STDIN_FILENO, buf, 1);
if (ch > 0)
ch = buf[0];
tcsetattr(STDIN_FILENO, TCSANOW, &old_attrs);
return ch;
#endif
}
62 changes: 62 additions & 0 deletions src/io.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* io (header) for RetroBASIC
Copyright (C) 2024 Maury Markowitz
This file is part of RetroBASIC.
RetroBASIC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RetroBASIC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RetroBASIC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */

#ifndef io_h
#define io_h

#include "stdhdr.h"

#if _WIN32
#include <conio.h>
#else
#include <sys/termios.h>
#endif

#include <unistd.h>

/**
* @file io.h
* @author Maury Markowitz
* @date 31 December 2024
* @brief Input/output and file handling routines.
*
*
*/

/**
* Waits for a single character. Used for GET.
*
* @param fd, the file descriptor, typically STDIN_FILENO.
* @return the keycode, NULL if an error occurred.
*/
int getbyte(int fd);

/**
* Gets a single keystroke, or null if no key is pressed. Used for INKEY$.
*
* @param fd, the file descriptor, typically STDIN_FILENO.
* @return the keycode, NULL if no key is pressed or an error occurred.
*
* See: https://stackoverflow.com/questions/1798511/how-to-avoid-pressing-enter-with-getchar-for-reading-a-single-character-only
*/
int getkey(int fd);


#endif /* io_h */
2 changes: 1 addition & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
/* simple version info for --version command line option */
static void print_version(void)
{
puts("RetroBASIC 2.0.1");
puts("RetroBASIC 2.0.2");
}

/* usage short form, just a list of the switches */
Expand Down
5 changes: 3 additions & 2 deletions src/parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@
MATSUB = 421,
MATMUL = 422,
MATSCA = 423,
MATFIL = 424
MATFIL = 424,
NUM = 425
};
#endif
/* Tokens. */
Expand Down Expand Up @@ -376,7 +377,7 @@
#define MATMUL 422
#define MATSCA 423
#define MATFIL 424

#define NUM 425



Expand Down
19 changes: 11 additions & 8 deletions src/parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ static expression_t *make_operator(int arity, int o)
%token MATSCA /* scalar multiply */
%token MATFIL /* fill an array with a value */

%token NUM /* introduced in Dartmouth for MAT INPUT, but we use it more generally */

%%

/* Grammar rules */
Expand Down Expand Up @@ -1442,14 +1444,15 @@ fn_x:
MID { $$ = MID; } |
SEG { $$ = SEG; } |
SUBSTR { $$ = SUBSTR; } |
ROUND { $$ = ROUND; } |
UBOUND { $$ = UBOUND; } |
LBOUND { $$ = LBOUND; } |
MATCON { $$ = MATCON; } |
MATIDN { $$ = MATIDN; } |
MATINV { $$ = MATINV; } |
MATTRN { $$ = MATTRN; } |
MATZER { $$ = MATZER; }
ROUND { $$ = ROUND; } |
UBOUND { $$ = UBOUND; } |
LBOUND { $$ = LBOUND; } |
MATCON { $$ = MATCON; } |
MATIDN { $$ = MATIDN; } |
MATINV { $$ = MATINV; } |
MATTRN { $$ = MATTRN; } |
MATZER { $$ = MATZER; } |
NUM { $$ = NUM; }
;

/* ultimately all expressions end up here in factor, which is either a
Expand Down
Loading

0 comments on commit 827d1b3

Please sign in to comment.