Browse Source

Prevent random seeks with BINARY mode files

The fread()/fwrite() "stream" familiy of functions were doing unexpected
things. This could be limited to GNU libC. At any rate that is the most
common libC on the Linux platform used by most SBCs and this caused errors
while having conversations with I2C devices.

I creates a set of macros to handle the reads and writes for BINARY mode
I/O, thinking that the bare UNIX I/O may not be implemented on some
platforms. This has yet to be tested. Those other platforms would likely
not have a problem with the random seek because you can't open I/O devices
with ordinary file commands.

Macros:
 -   BREAD(F, V): read()s binary data from file descriptor in FILE *F into V.
 -  BWRITE(F, V): write()s binary data V to file descriptor in FILE *F.
 -  BREADS(F, V): read()s binary data from file descriptor in FILE *F into
                  V->Buffer.
 - BWRITES(F, V): write()s binary data V-Buffer to file descriptor in FILE *F.

The BREADS/BWRITES handle writing the "Buffer" from a bwBASIC Variant. This
is used for reading and writing strings, hence the trailing S.

A test macro CMDEBUG was added to produce more diagnostic info. This will
likely go away.
tags/v3.20f
Jon Foster 3 years ago
parent
commit
e838df4a83
5 changed files with 188 additions and 138 deletions
  1. +28
    -0
      BAS-EXAMPLES/binfiles.bas
  2. +9
    -7
      BAS-EXAMPLES/opentest.bas
  3. +33
    -22
      bwb_inp.c
  4. +109
    -109
      bwb_prn.c
  5. +9
    -0
      bwbasic.c

+ 28
- 0
BAS-EXAMPLES/binfiles.bas View File

@@ -0,0 +1,28 @@
10 'Test / Demonstrate the use of the BINARY mode files.
: 'Contributed by ChipMaster
: 'NOTE: OPTION VERSION "HAARDT" must be run befor this loads or you
: ' get syntax and or illegal function call errors.
20 OPTION VERSION "HAARDT" : DEFINT A-Z : CLOSE : 'JIC
99 '*** Test wries, especially CHR$(0) ***
100 OPEN "O", #1, "TEST.DAT" : CLOSE #1 : ' ZAP file
110 OPEN "B", #1, "TEST.DAT"
120 M1$="" : FOR X= 0 TO 127 : M1$=M1$+CHR$(X) : NEXT
130 M2$="" : FOR X=128 TO 255 : M2$=M2$+CHR$(X) : NEXT
140 PUT #1, 1, M1$, M2$
199 '*** now rewind, reread ***
200 T1$ = STRING$(128, " ")
210 T2$ = T1$
220 GET #1, 1, T1$, T2$
230 CLOSE #1
239 '*** compare & spill results ***
240 IF T1$=M1$ AND T2$=M2$ THEN 270
250 PRINT "FAIL"
260 END
270 PRINT "Worked"
280 PRINT MID$(T1$, 34, 95)
290 PRINT "Press [ENTER] to view file";: LINE INPUT X$
300 ' "hexdump" is a *NIX tool. Substitute your hex deump tool of choice.
310 SHELL "hexdump -C TEST.DAT | less"

+ 9
- 7
BAS-EXAMPLES/opentest.bas View File

@@ -1,12 +1,14 @@
10 PRINT "OPENTEST.BAS -- Test OPEN, PRINT#, LINE INPUT#, and CLOSE"
10 PRINT "OPENTEST.BAS -- Test OPEN, EOF(), PRINT#, LINE INPUT#, and CLOSE"
20 OPEN "test.out" FOR OUTPUT AS # 1 20 OPEN "test.out" FOR OUTPUT AS # 1
30 PRINT #1,"This is line 1." 30 PRINT #1,"This is line 1."
40 PRINT #1, "This is line 2." 40 PRINT #1, "This is line 2."
45 PRINT #1, "ChipMaster WAS here!!"
50 CLOSE #1 50 CLOSE #1
60 OPEN "test.out" FOR INPUT AS #1
70 LINE INPUT #1,A$
80 LINE INPUT #1,B$
90 PRINT "Read from file:"
100 PRINT ">";A$
110 PRINT ">";B$
60 PRINT "Read from file:"
70 OPEN "test.out" FOR INPUT AS #1
80 WHILE NOT EOF(1)
90 LINE INPUT #1,A$
100 PRINT "> "; A$
110 WEND
120 CLOSE #1 120 CLOSE #1
130 PRINT " --- END OF LINE ---"

+ 33
- 22
bwb_inp.c View File

@@ -1293,6 +1293,19 @@ D71_GET (LineType * Line)
return (Line); return (Line);
} }


/* 20210916-ChipMaster: BINARY read/write macros - to tailor for each
platform, ASSuming it will need to be. Returns TRUE on success. */
#if TRUE /* Linux */
#define BWRITE(F,V) (write(fileno(F), &V, sizeof(V))==sizeof(V))
#define BREAD(F,V) (read(fileno(F), &V, sizeof(V))==sizeof(V))
#define BWRITES(F,V) (write(fileno(F), V->Buffer, V->Length)==V->Length)
#define BREADS(F,V) (read(fileno(F), V->Buffer, V->Length)==V->Length)
#else /* What it was */
#define BWRITE(F,V) (fwrite(&V, sizeof(V), 1, F)==F)
#define BREAD(F,V) (fread(&V, sizeof(V), 1, F)==F)
#define BWRITES(F,V) (fwrite(V->Buffer, V->Length, 1, F)==1)
#define BREADS(F,V) (fread(V->Buffer, V->Length, 1, F)==1)
#endif
extern int extern int
binary_get_put (VariableType * Variable, int IsPUT) binary_get_put (VariableType * Variable, int IsPUT)
{ {
@@ -1311,6 +1324,10 @@ binary_get_put (VariableType * Variable, int IsPUT)
WARN_VARIABLE_NOT_DECLARED; WARN_VARIABLE_NOT_DECLARED;
return FALSE; return FALSE;
} }
#ifdef CMDEBUG
errno = 0;
fputs("errno=0\n", stderr);
#endif
switch (Variant->VariantTypeCode) switch (Variant->VariantTypeCode)
{ {
case ByteTypeCode: case ByteTypeCode:
@@ -1319,7 +1336,7 @@ binary_get_put (VariableType * Variable, int IsPUT)
Value = (ByteType) Variant->Number; Value = (ByteType) Variant->Number;
if (IsPUT) if (IsPUT)
{ {
if (fwrite (&(Value), sizeof (Value), 1, My->CurrentFile->cfp) != 1)
if(!BWRITE(My->CurrentFile->cfp, Value))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
@@ -1327,7 +1344,7 @@ binary_get_put (VariableType * Variable, int IsPUT)
} }
else else
{ {
if (fread (&(Value), sizeof (Value), 1, My->CurrentFile->cfp) != 1)
if(!BREAD(My->CurrentFile->cfp, Value))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
@@ -1342,7 +1359,7 @@ binary_get_put (VariableType * Variable, int IsPUT)
Value = (IntegerType) Variant->Number; Value = (IntegerType) Variant->Number;
if (IsPUT) if (IsPUT)
{ {
if (fwrite (&(Value), sizeof (Value), 1, My->CurrentFile->cfp) != 1)
if(!BWRITE(My->CurrentFile->cfp, Value))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
@@ -1350,7 +1367,7 @@ binary_get_put (VariableType * Variable, int IsPUT)
} }
else else
{ {
if (fread (&(Value), sizeof (Value), 1, My->CurrentFile->cfp) != 1)
if(!BREAD(My->CurrentFile->cfp, Value))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
@@ -1365,7 +1382,7 @@ binary_get_put (VariableType * Variable, int IsPUT)
Value = (LongType) Variant->Number; Value = (LongType) Variant->Number;
if (IsPUT) if (IsPUT)
{ {
if (fwrite (&(Value), sizeof (Value), 1, My->CurrentFile->cfp) != 1)
if(!BWRITE(My->CurrentFile->cfp, Value))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
@@ -1373,7 +1390,7 @@ binary_get_put (VariableType * Variable, int IsPUT)
} }
else else
{ {
if (fread (&(Value), sizeof (Value), 1, My->CurrentFile->cfp) != 1)
if(!BREAD(My->CurrentFile->cfp, Value))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
@@ -1388,7 +1405,7 @@ binary_get_put (VariableType * Variable, int IsPUT)
Value = (CurrencyType) Variant->Number; Value = (CurrencyType) Variant->Number;
if (IsPUT) if (IsPUT)
{ {
if (fwrite (&(Value), sizeof (Value), 1, My->CurrentFile->cfp) != 1)
if(!BWRITE(My->CurrentFile->cfp, Value))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
@@ -1396,7 +1413,7 @@ binary_get_put (VariableType * Variable, int IsPUT)
} }
else else
{ {
if (fread (&(Value), sizeof (Value), 1, My->CurrentFile->cfp) != 1)
if(!BREAD(My->CurrentFile->cfp, Value))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
@@ -1411,7 +1428,7 @@ binary_get_put (VariableType * Variable, int IsPUT)
Value = (SingleType) Variant->Number; Value = (SingleType) Variant->Number;
if (IsPUT) if (IsPUT)
{ {
if (fwrite (&(Value), sizeof (Value), 1, My->CurrentFile->cfp) != 1)
if(!BWRITE(My->CurrentFile->cfp, Value))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
@@ -1419,7 +1436,7 @@ binary_get_put (VariableType * Variable, int IsPUT)
} }
else else
{ {
if (fread (&(Value), sizeof (Value), 1, My->CurrentFile->cfp) != 1)
if(!BREAD(My->CurrentFile->cfp, Value))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
@@ -1434,7 +1451,7 @@ binary_get_put (VariableType * Variable, int IsPUT)
Value = (DoubleType) Variant->Number; Value = (DoubleType) Variant->Number;
if (IsPUT) if (IsPUT)
{ {
if (fwrite (&(Value), sizeof (Value), 1, My->CurrentFile->cfp) != 1)
if(!BWRITE(My->CurrentFile->cfp, Value))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
@@ -1442,7 +1459,7 @@ binary_get_put (VariableType * Variable, int IsPUT)
} }
else else
{ {
if (fread (&(Value), sizeof (Value), 1, My->CurrentFile->cfp) != 1)
if(!BREAD(My->CurrentFile->cfp, Value))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
@@ -1455,16 +1472,13 @@ binary_get_put (VariableType * Variable, int IsPUT)
if (IsPUT) if (IsPUT)
{ {
#if FALSE /* keep this ... */ #if FALSE /* keep this ... */
if (fwrite
(&(Variant->Length), sizeof (Variant->Length), 1,
My->CurrentFile->cfp) != 1)
if(!BWRITE(My->CurrentFile->cfp, Variant->Length))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
} }
#endif #endif
if (fwrite (Variant->Buffer, Variant->Length, 1, My->CurrentFile->cfp)
!= 1)
if(!BWRITES(My->CurrentFile->cfp, Variant))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
@@ -1473,16 +1487,13 @@ binary_get_put (VariableType * Variable, int IsPUT)
else else
{ {
#if FALSE /* keep this ... */ #if FALSE /* keep this ... */
if (fread
(&(Variant->Length), sizeof (Variant->Length), 1,
My->CurrentFile->cfp) != 1)
if(!BREAD(My->CurrentFile->cfp, Variant->Length))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;
} }
#endif #endif
if (fread (Variant->Buffer, Variant->Length, 1, My->CurrentFile->cfp) !=
1)
if(!BREADS(My->CurrentFile->cfp, Variant))
{ {
WARN_DISK_IO_ERROR; WARN_DISK_IO_ERROR;
return FALSE; return FALSE;


+ 109
- 109
bwb_prn.c View File

@@ -1,26 +1,26 @@
/*************************************************************** /***************************************************************
bwb_prn.c Print and Error-Handling Commands bwb_prn.c Print and Error-Handling Commands
for Bywater BASIC Interpreter for Bywater BASIC Interpreter
Copyright (c) 1993, Ted A. Campbell Copyright (c) 1993, Ted A. Campbell
Bywater Software Bywater Software
email: tcamp@delphi.com email: tcamp@delphi.com
Copyright and Permissions Information: Copyright and Permissions Information:
All U.S. and international rights are claimed by the author, All U.S. and international rights are claimed by the author,
Ted A. Campbell. Ted A. Campbell.
This software is released under the terms of the GNU General This software is released under the terms of the GNU General
Public License (GPL), which is distributed with this software Public License (GPL), which is distributed with this software
in the file "COPYING". The GPL specifies the terms under in the file "COPYING". The GPL specifies the terms under
which users may copy and use the software in this distribution. which users may copy and use the software in this distribution.
A separate license is available for commercial distribution, A separate license is available for commercial distribution,
for information on which you should contact the author. for information on which you should contact the author.
***************************************************************/ ***************************************************************/


/*---------------------------------------------------------------*/ /*---------------------------------------------------------------*/
@@ -75,9 +75,9 @@ For example:
1) some use '%' for strings, others use '%' for numbers, others consider '%' as a lieral. 1) some use '%' for strings, others use '%' for numbers, others consider '%' as a lieral.
2) some count a leading or traling signs in the width, while others do not. 2) some count a leading or traling signs in the width, while others do not.
3) when a value requires more digits than the assigned width: 3) when a value requires more digits than the assigned width:
a) some truncate the displayed value to the width,
b) some expand the width,
c) some print a number of '%' or '*', and
a) some truncate the displayed value to the width,
b) some expand the width,
c) some print a number of '%' or '*', and
d) some halt processing. d) some halt processing.
There is no perfect solution that will work for all possible dialects. There is no perfect solution that will work for all possible dialects.
*/ */
@@ -110,7 +110,7 @@ There is no perfect solution that will work for all possible dialects.
int int
is_empty_string (char *Buffer) is_empty_string (char *Buffer)
{ {


if (Buffer == NULL) if (Buffer == NULL)
{ {
@@ -132,7 +132,7 @@ FileType *
find_file_by_name (char *FileName) find_file_by_name (char *FileName)
{ {
FileType *F; FileType *F;
if (is_empty_string (FileName)) if (is_empty_string (FileName))
{ {
/* the rules for Console and Printer vary by command */ /* the rules for Console and Printer vary by command */
@@ -164,7 +164,7 @@ FileType *
find_file_by_number (int FileNumber) find_file_by_number (int FileNumber)
{ {
FileType *F; FileType *F;


/* handle MAGIC file numbers */ /* handle MAGIC file numbers */
if (FileNumber <= 0) if (FileNumber <= 0)
@@ -196,7 +196,7 @@ file_new (void)
{ {
/* search for an empty slot. If not found, add a new slot. */ /* search for an empty slot. If not found, add a new slot. */
FileType *F; FileType *F;
assert( My != NULL ); assert( My != NULL );
for (F = My->FileHead; F != NULL; F = F->next) for (F = My->FileHead; F != NULL; F = F->next)
{ {
@@ -224,7 +224,7 @@ void
file_clear (FileType * F) file_clear (FileType * F)
{ {
/* clean up a file slot that is no longer needed */ /* clean up a file slot that is no longer needed */
assert (F != NULL); assert (F != NULL);


clear_virtual_by_file (F->FileNumber); clear_virtual_by_file (F->FileNumber);
@@ -258,7 +258,7 @@ file_next_number (void)
{ {
int FileNumber; int FileNumber;
FileType *F; FileType *F;


FileNumber = 0; FileNumber = 0;
assert( My != NULL ); assert( My != NULL );
@@ -281,12 +281,12 @@ file_next_number (void)




/*************************************************************** /***************************************************************
FUNCTION: bwx_putc() FUNCTION: bwx_putc()
DESCRIPTION: This function outputs a single character DESCRIPTION: This function outputs a single character
to the default output device. to the default output device.
***************************************************************/ ***************************************************************/


static void static void
@@ -295,7 +295,7 @@ CleanNumericString (char *prnbuf, int RemoveDot)
/* remove trailing zeroes */ /* remove trailing zeroes */
char *E; char *E;
char *D; char *D;
assert (prnbuf != NULL); assert (prnbuf != NULL);


E = bwb_strchr (prnbuf, 'E'); E = bwb_strchr (prnbuf, 'E');
@@ -413,7 +413,7 @@ CountDigits (char *Buffer)
{ {
int NumDigits; int NumDigits;
char *P; char *P;
assert (Buffer != NULL); assert (Buffer != NULL);




@@ -440,20 +440,20 @@ extern void
FormatBasicNumber (DoubleType Input, char *Output /* [ NUMLEN ] */ ) FormatBasicNumber (DoubleType Input, char *Output /* [ NUMLEN ] */ )
{ {
/******************************************************************************* /*******************************************************************************
This is essentially sprintf( Output, "%g", Input ),
This is essentially sprintf( Output, "%g", Input ),
except the rules for selecting between "%e", "%f", and "%d" are different. except the rules for selecting between "%e", "%f", and "%d" are different.


The C rules depend upon the value of the exponent. The C rules depend upon the value of the exponent.
The BASIC rules depend upon the number of significant digits. The BASIC rules depend upon the number of significant digits.


The results of this routine have been verified by the NBS2 test suite, so... The results of this routine have been verified by the NBS2 test suite, so...
THINK VERY CAREFULLY BEFORE MAKING ANY CHANGES TO THIS ROUTINE.
THINK VERY CAREFULLY BEFORE MAKING ANY CHANGES TO THIS ROUTINE.
*******************************************************************************/ *******************************************************************************/
char *E; char *E;
assert (Output != NULL); assert (Output != NULL);


assert( My != NULL ); assert( My != NULL );
@@ -533,7 +533,7 @@ LineType *
bwb_LPRINT (LineType * l) bwb_LPRINT (LineType * l)
{ {
int IsCSV; int IsCSV;
assert (l != NULL); assert (l != NULL);


assert( My != NULL ); assert( My != NULL );
@@ -546,14 +546,14 @@ bwb_LPRINT (LineType * l)




/*************************************************************** /***************************************************************
FUNCTION: bwb_print() FUNCTION: bwb_print()
DESCRIPTION: This function implements the BASIC PRINT DESCRIPTION: This function implements the BASIC PRINT
command. command.
SYNTAX: PRINT [# device-number,][USING format-string$;] expressions... SYNTAX: PRINT [# device-number,][USING format-string$;] expressions...
***************************************************************/ ***************************************************************/




@@ -563,7 +563,7 @@ bwb_print_at (LineType * l)
int position; int position;
int r; int r;
int c; int c;
assert (l != NULL); assert (l != NULL);




@@ -631,7 +631,7 @@ parse_file_number (LineType * l)
{ {
/* ... # FileNumber , ... */ /* ... # FileNumber , ... */
int FileNumber; int FileNumber;
assert (l != NULL); assert (l != NULL);




@@ -645,7 +645,7 @@ parse_file_number (LineType * l)
assert( My->CurrentVersion != NULL ); assert( My->CurrentVersion != NULL );
if (My->CurrentVersion->OptionVersionValue & (C77)) if (My->CurrentVersion->OptionVersionValue & (C77))
{ {
/*
/*
CBASIC-II: SERIAL & RANDOM file writes CBASIC-II: SERIAL & RANDOM file writes
PRINT # file_number ; expression [, expression] ' SERIAL write PRINT # file_number ; expression [, expression] ' SERIAL write
PRINT # file_number , record_number ; expression [, expression] ' RANDOM write PRINT # file_number , record_number ; expression [, expression] ' RANDOM write
@@ -667,7 +667,7 @@ parse_file_number (LineType * l)


if (line_skip_CommaChar (l) /* comma specific */ ) if (line_skip_CommaChar (l) /* comma specific */ )
{ {
/*
/*
PRINT # file_number , record_number ; expression [, expression] ' RANDOM write PRINT # file_number , record_number ; expression [, expression] ' RANDOM write
*/ */
/* get the RecordNumber */ /* get the RecordNumber */
@@ -719,9 +719,9 @@ parse_file_number (LineType * l)
} }
return TRUE; return TRUE;
} }
/*
/*
SERIAL file writes: SERIAL file writes:
PRINT # file_number
PRINT # file_number
PRINT # file_number [, expression] PRINT # file_number [, expression]
*/ */
if (FileNumber < 0) if (FileNumber < 0)
@@ -767,7 +767,7 @@ LineType *
bwb_PRINT (LineType * l) bwb_PRINT (LineType * l)
{ {
int IsCSV; int IsCSV;
assert (l != NULL); assert (l != NULL);


IsCSV = FALSE; IsCSV = FALSE;
@@ -785,13 +785,13 @@ bwb_PRINT (LineType * l)
} }


/*************************************************************** /***************************************************************
FUNCTION: internal_print() FUNCTION: internal_print()
DESCRIPTION: This function implements the PRINT DESCRIPTION: This function implements the PRINT
command, utilizing a specified file our command, utilizing a specified file our
output device. output device.
***************************************************************/ ***************************************************************/


static int static int
@@ -799,7 +799,7 @@ buff_read_using (char *buffer, int *position, char *format_string,
int format_length) int format_length)
{ {
int p; int p;
assert (buffer != NULL); assert (buffer != NULL);
assert (position != NULL); assert (position != NULL);
assert (format_string != NULL); assert (format_string != NULL);
@@ -950,7 +950,7 @@ internal_print (LineType * l, int IsCSV)
char *format_string; char *format_string;
int format_length; int format_length;
int format_position; int format_position;
assert (l != NULL); assert (l != NULL);




@@ -974,7 +974,7 @@ internal_print (LineType * l, int IsCSV)
if (My->CurrentVersion->OptionVersionValue & (C77) if (My->CurrentVersion->OptionVersionValue & (C77)
&& My->CurrentFile->FileNumber > 0) && My->CurrentFile->FileNumber > 0)
{ {
/*
/*
** **
** CBASIC-II files are CSV files. ** CBASIC-II files are CSV files.
** **
@@ -999,7 +999,7 @@ internal_print (LineType * l, int IsCSV)
} }
OutputCR = TRUE; OutputCR = TRUE;
} }
else if (My->CurrentVersion->OptionVersionValue & (B15|T80|HB1|HB2)
else if (My->CurrentVersion->OptionVersionValue & (B15|T80|HB1|HB2)
&& line_skip_word (l, "AT")) && line_skip_word (l, "AT"))
{ {
/* PRINT AT position, ... */ /* PRINT AT position, ... */
@@ -1064,9 +1064,9 @@ internal_print (LineType * l, int IsCSV)
/* resolve the string */ /* resolve the string */
if (My->IsErrorPending /* Keep This */ ) if (My->IsErrorPending /* Keep This */ )
{ {
/*
/*
** **
** this might look odd...
** this might look odd...
** but we want to abort printing on the first warning. ** but we want to abort printing on the first warning.
** The expression list could include a function with side-effects, ** The expression list could include a function with side-effects,
** so any error should immediately halt further evaluation. ** so any error should immediately halt further evaluation.
@@ -1100,13 +1100,13 @@ internal_print (LineType * l, int IsCSV)




/*************************************************************** /***************************************************************
FUNCTION: print_using_variant() FUNCTION: print_using_variant()
DESCRIPTION: This function gets the PRINT USING DESCRIPTION: This function gets the PRINT USING
format string, returning a structure format string, returning a structure
to the format. to the format.
***************************************************************/ ***************************************************************/
static void static void
print_using_number (char *buffer, int *position, VariantType * e) print_using_number (char *buffer, int *position, VariantType * e)
@@ -1127,7 +1127,7 @@ print_using_number (char *buffer, int *position, VariantType * e)
char TailChar; char TailChar;
int p; int p;
char *tbuf; char *tbuf;
assert (buffer != NULL); assert (buffer != NULL);
assert (position != NULL); assert (position != NULL);
assert (e != NULL); assert (e != NULL);
@@ -1436,9 +1436,9 @@ print_using_number (char *buffer, int *position, VariantType * e)
{ {
if (i < commas && tbuf[i] == FillChar) if (i < commas && tbuf[i] == FillChar)
{ {
/*
/*
Ignore the same number of leading spaces as there are commas. Ignore the same number of leading spaces as there are commas.
While not perfect for all possible cases,
While not perfect for all possible cases,
it is usually good enough for practical purposes. it is usually good enough for practical purposes.
*/ */
} }
@@ -1471,7 +1471,7 @@ print_using_string (char *buffer, int *position, VariantType * e)
*/ */
int p; int p;
char *tbuf; char *tbuf;
assert (buffer != NULL); assert (buffer != NULL);
assert (position != NULL); assert (position != NULL);
assert (e != NULL); assert (e != NULL);
@@ -1563,12 +1563,12 @@ print_using_string (char *buffer, int *position, VariantType * e)
static int static int
is_magic_string (char *buffer) is_magic_string (char *buffer)
{ {
/*
/*
for the character string pointed to 'buffer': for the character string pointed to 'buffer':
return TRUE if it is a MagicString sequence, return TRUE if it is a MagicString sequence,
return FALSE otherwise. return FALSE otherwise.
*/ */
assert (buffer != NULL); assert (buffer != NULL);




@@ -1599,12 +1599,12 @@ is_magic_string (char *buffer)
static int static int
is_magic_number (char *buffer) is_magic_number (char *buffer)
{ {
/*
/*
for the character string pointed to 'buffer': for the character string pointed to 'buffer':
return TRUE if it is a MagicNumber sequence, return TRUE if it is a MagicNumber sequence,
return FALSE otherwise. return FALSE otherwise.
*/ */
assert (buffer != NULL); assert (buffer != NULL);


/* 1 character sequences */ /* 1 character sequences */
@@ -1684,7 +1684,7 @@ print_using_variant (char *buffer, int *position, VariantType * e, int IsCSV)
'e' is the current expression to print. 'e' is the current expression to print.
*/ */
int IsUsed; int IsUsed;
assert (buffer != NULL); assert (buffer != NULL);
assert (position != NULL); assert (position != NULL);
assert (e != NULL); assert (e != NULL);
@@ -1775,9 +1775,9 @@ print_using_variant (char *buffer, int *position, VariantType * e, int IsCSV)
{ {
/* /*
** **
** PRINT A$
** PRINT USING "";A$
** PRINT USING "ABC";A$
** PRINT A$
** PRINT USING "";A$
** PRINT USING "ABC";A$
** **
*/ */
if (IsCSV) if (IsCSV)
@@ -1795,12 +1795,12 @@ print_using_variant (char *buffer, int *position, VariantType * e, int IsCSV)
{ {
/* /*
** **
** PRINT X
** PRINT USING "";X
** PRINT USING "ABC";X
** PRINT X
** PRINT USING "";X
** PRINT USING "ABC";X
** **
** [space]number[space] POSITIVE or ZERO ** [space]number[space] POSITIVE or ZERO
** [minus]number[space] NEGATIVE
** [minus]number[space] NEGATIVE
** **
**/ **/
char *tbuf; char *tbuf;
@@ -1829,21 +1829,21 @@ print_using_variant (char *buffer, int *position, VariantType * e, int IsCSV)
} }


/*************************************************************** /***************************************************************
FUNCTION: xputs() FUNCTION: xputs()
DESCRIPTION: This function outputs a null-terminated DESCRIPTION: This function outputs a null-terminated
string to a specified file or output string to a specified file or output
device. device.
***************************************************************/ ***************************************************************/


static void static void
xputs (char *buffer) xputs (char *buffer)
{ {
assert (buffer != NULL); assert (buffer != NULL);
assert( My != NULL );
assert( My != NULL );
assert (My->CurrentFile != NULL); assert (My->CurrentFile != NULL);


if (My->CurrentFile->width > 0) if (My->CurrentFile->width > 0)
@@ -1866,11 +1866,11 @@ xputs (char *buffer)




/*************************************************************** /***************************************************************
FUNCTION: next_zone() FUNCTION: next_zone()
DESCRIPTION: Advance to the next print zone. DESCRIPTION: Advance to the next print zone.
***************************************************************/ ***************************************************************/
static void static void
next_zone (void) next_zone (void)
@@ -1882,7 +1882,7 @@ next_zone (void)
{ {
/* /*
** **
** check to see if width will be exceeded
** check to see if width will be exceeded
** **
*/ */
int LastZoneColumn; int LastZoneColumn;
@@ -1921,14 +1921,14 @@ next_zone (void)
} }


/*************************************************************** /***************************************************************
FUNCTION: xputc1() FUNCTION: xputc1()
DESCRIPTION: This function outputs a character to a DESCRIPTION: This function outputs a character to a
specified file or output device, checking specified file or output device, checking
to be sure the PRINT width is within to be sure the PRINT width is within
the bounds specified for that device. the bounds specified for that device.
***************************************************************/ ***************************************************************/


static void static void
@@ -1941,16 +1941,16 @@ xputc1 (char c)
{ {
/* /*
** **
** check to see if width has been exceeded
** check to see if width has been exceeded
** **
*/ */
if (c != '\n') if (c != '\n')
{ {
/* /*
** **
** REM this should print one line, not two lines
** REM this should print one line, not two lines
** WIDTH 80 ** WIDTH 80
** PRINT SPACE$( 80 )
** PRINT SPACE$( 80 )
** **
*/ */
if (My->CurrentFile->col > My->CurrentFile->width) if (My->CurrentFile->col > My->CurrentFile->width)
@@ -1968,12 +1968,12 @@ xputc1 (char c)
} }


/*************************************************************** /***************************************************************
FUNCTION: xputc2() FUNCTION: xputc2()
DESCRIPTION: This function sends a character to a DESCRIPTION: This function sends a character to a
specified file or output device. specified file or output device.
***************************************************************/ ***************************************************************/




@@ -1989,7 +1989,7 @@ xputc2 (char c)
{ {
/* /*
** **
** CBASIC-II: RANDOM files are padded on the right with spaces
** CBASIC-II: RANDOM files are padded on the right with spaces
** **
*/ */
if (My->CurrentVersion->OptionVersionValue & (C77)) if (My->CurrentVersion->OptionVersionValue & (C77))
@@ -2009,13 +2009,13 @@ xputc2 (char c)
} }
/* /*
** **
** output the character
** output the character
** **
*/ */
fputc (c, My->CurrentFile->cfp); fputc (c, My->CurrentFile->cfp);
/* /*
** **
** NULLS
** NULLS
** **
*/ */
if (My->LPRINT_NULLS > 0) if (My->LPRINT_NULLS > 0)
@@ -2030,7 +2030,7 @@ xputc2 (char c)
} }
/* /*
** **
** update current column position
** update current column position
** **
*/ */
My->CurrentFile->col = 1; My->CurrentFile->col = 1;
@@ -2039,13 +2039,13 @@ xputc2 (char c)
} }
/* /*
** **
** output the character
** output the character
** **
*/ */
fputc (c, My->CurrentFile->cfp); fputc (c, My->CurrentFile->cfp);
/* /*
** **
** update current column position
** update current column position
** **
*/ */
My->CurrentFile->col++; My->CurrentFile->col++;
@@ -2067,7 +2067,7 @@ S70_PUT (LineType * l)
/* PUT filename$ , value [, ...] */ /* PUT filename$ , value [, ...] */
VariantType e; VariantType e;
VariantType *E; VariantType *E;
assert (l != NULL); assert (l != NULL);
assert( My != NULL ); assert( My != NULL );
assert( My->CurrentVersion != NULL ); assert( My->CurrentVersion != NULL );
@@ -2222,7 +2222,7 @@ D71_PUT (LineType * l)
{ {
/* PUT # file_number [ , RECORD record_number ] */ /* PUT # file_number [ , RECORD record_number ] */
int file_number; int file_number;
assert (l != NULL); assert (l != NULL);
assert( My != NULL ); assert( My != NULL );


@@ -2319,7 +2319,7 @@ H14_PUT (LineType * Line)
/* PUT # FileNumber [ , RecordNumber ] ' RANDOM */ /* PUT # FileNumber [ , RecordNumber ] ' RANDOM */
/* PUT # FileNumber , [ BytePosition ] , scalar [,...] ' BINARY */ /* PUT # FileNumber , [ BytePosition ] , scalar [,...] ' BINARY */
int file_number; int file_number;
assert (Line != NULL); assert (Line != NULL);
assert( My != NULL ); assert( My != NULL );


@@ -2471,7 +2471,7 @@ H14_PUT (LineType * Line)
extern LineType * extern LineType *
bwb_PUT (LineType * Line) bwb_PUT (LineType * Line)
{ {
assert (Line != NULL); assert (Line != NULL);
assert( My != NULL ); assert( My != NULL );
assert( My->CurrentVersion != NULL ); assert( My->CurrentVersion != NULL );
@@ -2494,14 +2494,14 @@ bwb_PUT (LineType * Line)




/*************************************************************** /***************************************************************
FUNCTION: bwb_write() FUNCTION: bwb_write()
DESCRIPTION: This C function implements the BASIC WRITE DESCRIPTION: This C function implements the BASIC WRITE
command. command.
SYNTAX: WRITE [# device-number,] element [, element ].... SYNTAX: WRITE [# device-number,] element [, element ]....
***************************************************************/ ***************************************************************/




@@ -2509,7 +2509,7 @@ extern LineType *
bwb_WRITE (LineType * l) bwb_WRITE (LineType * l)
{ {
int IsCSV; int IsCSV;
assert (l != NULL); assert (l != NULL);


IsCSV = TRUE; IsCSV = TRUE;
@@ -2529,7 +2529,7 @@ file_write_matrix (LineType * l, char delimit)
/* MAT PUT filenumber , matrix [;|,] ... */ /* MAT PUT filenumber , matrix [;|,] ... */
/* Array must be 1, 2 or 3 dimensions */ /* Array must be 1, 2 or 3 dimensions */
/* Array may be either NUMBER or STRING */ /* Array may be either NUMBER or STRING */
assert (l != NULL); assert (l != NULL);


do do
@@ -2617,7 +2617,7 @@ file_write_matrix (LineType * l, char delimit)
OPTION BASE 0 OPTION BASE 0
DIM A(5) DIM A(5)
... ...
MAT PRINT A
MAT PRINT A
... ...
FOR I = 0 TO 5 FOR I = 0 TO 5
PRINT A(I) PRINT A(I)
@@ -2670,7 +2670,7 @@ file_write_matrix (LineType * l, char delimit)
OPTION BASE 0 OPTION BASE 0
DIM B(2,3) DIM B(2,3)
... ...
MAT PRINT B
MAT PRINT B
... ...
FOR I = 0 TO 2 FOR I = 0 TO 2
FOR J = 0 TO 3 FOR J = 0 TO 3
@@ -2730,7 +2730,7 @@ file_write_matrix (LineType * l, char delimit)
OPTION BASE 0 OPTION BASE 0
DIM C(2,3,4) DIM C(2,3,4)
... ...
MAT PRINT C
MAT PRINT C
... ...
FOR I = 0 TO 2 FOR I = 0 TO 2
FOR J = 0 TO 3 FOR J = 0 TO 3
@@ -2808,7 +2808,7 @@ bwb_MAT_PUT (LineType * l)
/* Array may be either NUMBER or STRING */ /* Array may be either NUMBER or STRING */
VariantType x; VariantType x;
VariantType *X; VariantType *X;
assert (l != NULL); assert (l != NULL);
assert( My != NULL ); assert( My != NULL );
assert( My->SYSOUT != NULL ); assert( My->SYSOUT != NULL );
@@ -2917,7 +2917,7 @@ bwb_mat_dump (LineType * l, int IsWrite)
/* Array must be 1, 2 or 3 dimensions */ /* Array must be 1, 2 or 3 dimensions */
/* Array may be either NUMBER or STRING */ /* Array may be either NUMBER or STRING */
char delimit; char delimit;
assert (l != NULL); assert (l != NULL);
assert( My != NULL ); assert( My != NULL );
assert( My->SYSOUT != NULL ); assert( My->SYSOUT != NULL );
@@ -2953,7 +2953,7 @@ bwb_mat_dump (LineType * l, int IsWrite)
extern LineType * extern LineType *
bwb_MAT_WRITE (LineType * l) bwb_MAT_WRITE (LineType * l)
{ {
assert (l != NULL); assert (l != NULL);


return bwb_mat_dump (l, TRUE); return bwb_mat_dump (l, TRUE);
@@ -2962,7 +2962,7 @@ bwb_MAT_WRITE (LineType * l)
extern LineType * extern LineType *
bwb_MAT_PRINT (LineType * l) bwb_MAT_PRINT (LineType * l)
{ {
assert (l != NULL); assert (l != NULL);


return bwb_mat_dump (l, FALSE); return bwb_mat_dump (l, FALSE);


+ 9
- 0
bwbasic.c View File

@@ -2177,6 +2177,15 @@ bwx_Error (int ERR, char *ErrorMessage)
My->ERL = NULL; /* bwx_Error, ERR == 0 */ My->ERL = NULL; /* bwx_Error, ERR == 0 */
bwb_strcpy (My->ERROR4, ""); /* bwx_Error, ERR == 0 */ bwb_strcpy (My->ERROR4, ""); /* bwx_Error, ERR == 0 */
return FALSE; return FALSE;
#ifdef CMDEBUG
case 57: /* ChipMaster testing ... */
fprintf(stderr, "I/O Error: feof=%d ferror=%d errno=%d\n",
(int)feof(My->CurrentFile->cfp),
(int)ferror(My->CurrentFile->cfp),
errno
);
break;
#endif
case 6: /* WARN_OVERFLOW */ case 6: /* WARN_OVERFLOW */
case 11: /* WARN_DIVISION_BY_ZERO */ case 11: /* WARN_DIVISION_BY_ZERO */
case 15: /* WARN_STRING_TOO_LONG */ case 15: /* WARN_STRING_TOO_LONG */


Loading…
Cancel
Save