From: DTS66::LEDERMAN "B. Z. Lederman" 23-NOV-1992 09:22:30.95
To: MX%"[email-masked]"
Cc: LEDERMAN

I'm working on compiling your BASIC interpreter in spare
 moments, and see still more changes which have to be made.

    The first problem is that you have indented many of your
 #ifdef statements.  This is not allowed in ANSI C: the # must be
 in column 1.  I've had to remove the indentations.

    When compiling with standards checking on, there are many
 instances where

 return NULL;

 results in an error, because NULL is defined as a pointer to
 zero, not zero.  There are a couple of fixes for this.  I've
 chosen to change the lines to

 return (int) NULL;

    The biggest problem I have now is in command selection.  I can
 run the interpreter and input statements, such as

100 LET A = 1
110 LET B = 2
120 LET C = A + B
130 PRINT C

    and so on.  However, as soon as I enter a command such as
 LIST, RUN, SAVE, etc., I get an access violation (indicating that
 the program is trying to access memory outside the range of the
 program).  The error is always on the same line within BWBASIC.C:

=====================================================================

      if ( l->cmdnum > -1 )
         {

#if INTENSIVE_DEBUG
         sprintf( bwb_ebuf, "in bwb_xline(): executing <%s>", l->buffer );
         bwb_debug( bwb_ebuf );
#endif

         /* execute the command vector */

         r = ( bwb_cmdtable[ l->cmdnum ].vector ) ( l ); /* <--- THIS LINE */

#if INTENSIVE_DEBUG
	 if ( l->cmdnum == getcmdnum( "GOSUB" ) )
	    {
	    sprintf( bwb_ebuf, "in bwb_xline(): returning from GOSUB, position <%d>",
	       l->position );
	    bwb_debug( bwb_ebuf );
            }
#endif

         /* If the command was RETURN OR GOTO, then we must break out of
            the loop at this point; the rest of the line is irrelevant */

=====================================================================

    I have appended the discussions I have had with other
 developers on what I've found so far in the interpreter.


             <<< EISNER::DUA3:[NOTES$LIBRARY]DEC_SOFTWARE.NOTE;1 >>>
                               -< DEC_SOFTWARE >-

================================================================================
Note 215.3                      Missing from RTL                          3 of 7
EISNER::LEDERMAN "Bart Z. Lederman"                  11 lines  12-NOV-1992 14:46
                              -< rmdir missing? >-
--------------------------------------------------------------------------------
    I am trying to port some software (Bywater BASIC interpreter from Duke,
    in case someone has already done it) to VMS and noticed that rmdir is
    missing from VAXCRTL.
    
    The RTL does have mkdir and chdir.  It seems very strange to me that
    those two functions would be present and rmdir would be absent.
    
    Does anyone have an explanation?
    
    Also, does anyone have a replacement?  (Not critical, as the BASIC
    interpreter can easily get along without a RMDIR function).

================================================================================
Note 215.4                      Missing from RTL                          4 of 7
EISNER::BURNET "John Burnet"                         15 lines  12-NOV-1992 15:12
                -< Try delete() instead of rmdir() or unlink() >-
--------------------------------------------------------------------------------
>    The RTL does have mkdir and chdir.  It seems very strange to me that
>    those two functions would be present and rmdir would be absent.
    
On Unix, rmdir() is a system call, not a library routine.  It may or may not
exist in C RTLs on non-Unix systems, depending on how zealous the implementors
were feeling, and it's not specified by the ANSI C standard.  On VMS, the
authors of the RTL probably figured that people can simply use

#define rmdir delete
#define unlink delete

to use the delete() function to delete files or empty directories.  The
file-specification and directory-specification syntax is system-specific
in any case, so some customization for non-Unix systems would seem to be
inevitable regardless of the function names.

================================================================================
Note 215.5                      Missing from RTL                          5 of 7
EISNER::LEDERMAN "Bart Z. Lederman"                   6 lines  12-NOV-1992 18:59
                             -< Making progress. >-
--------------------------------------------------------------------------------
    Thanks for the note.  It turns out the source code uses unlink() as
    well, which I couldn't find anywhere and thought might be missing from
    the source code.
    
    There is a third function which isn't defined, I'll have to look it up
    and post it as well.

================================================================================
Note 215.6                      Missing from RTL                          6 of 7
EISNER::LEDERMAN "Bart Z. Lederman"                  15 lines  13-NOV-1992 19:13
                        -< O.K.: now, what is putenv? >-
--------------------------------------------------------------------------------
    I'm making some progress, and have also talked to the original author.
    
    The one remaining undefined call is putenv().  I can get around this
    for a while by just disabling the command which uses it, but if anyone
    knows what putenv is (it's not in the VAX C manual) a replacement may
    be possible.
    
    The interpreter isn't working yet.  It accepts statements, but commands
    (LIST, SAVE, etc.) get an access violation.  The compiler does give
    some warnings about non-portable conversion between pointers and
    integers when /STANDARD=PORTABLE is used, and no warnings when
    /STANDARD isn't used, so I'm not sure how to track down the error. 
    I've been assured that it does compile and run on other operating
    systems (I gather primarily UNIX).  I'm not too confident about
    tracking down this kind of error, but I'm going to try.

================================================================================
Note 215.7                      Missing from RTL                          7 of 7
EISNER::MAHAN "Patrick Mahan, GAPSIG Moderator"      36 lines  13-NOV-1992 19:56
                             -< This should help >-
--------------------------------------------------------------------------------
#             <<< Note 215.6 by EISNER::LEDERMAN "Bart Z. Lederman" >>>
#                         -< O.K.: now, what is putenv? >-
# 
#     I'm making some progress, and have also talked to the original author.
#     
#     The one remaining undefined call is putenv().  I can get around this
#     for a while by just disabling the command which uses it, but if anyone
#     knows what putenv is (it's not in the VAX C manual) a replacement may
#     be possible.
#     
#     The interpreter isn't working yet.  It accepts statements, but commands
#     (LIST, SAVE, etc.) get an access violation.  The compiler does give
#     some warnings about non-portable conversion between pointers and
#     integers when /STANDARD=PORTABLE is used, and no warnings when
#     /STANDARD isn't used, so I'm not sure how to track down the error. 
#     I've been assured that it does compile and run on other operating
#     systems (I gather primarily UNIX).  I'm not too confident about
#     tracking down this kind of error, but I'm going to try.
# 

	putenv() was a way to declare environment variables under Unix.
	The same is not true within VMS, except that you might want to
	satisfy this using LIB$SET_SYMBOL to create DCL symbols.

	If you would post the ACCVIO message here we probably could be
	of some help.  The reason /STANDARD=PORTABLE gives warnings is
	that you will find code where the following is true:

		char *cp;

		cp = strchr(str, '.');

	If there is no forward declaration of "strchr" then C assumes
	it is a function returning "int" and thus the warnings.

             <<< EISNER::DUA3:[NOTES$LIBRARY]DEC_SOFTWARE.NOTE;1 >>>
                               -< DEC_SOFTWARE >-
================================================================================
Note 553.0         No white space before #if, #ifdef and #end?         3 replies
EISNER::LEDERMAN "Bart Z. Lederman"                  11 lines  12-NOV-1992 14:48
--------------------------------------------------------------------------------
    I'm trying to port the Bywater BASIC interpreter to VAX/VMS and noticed
    that the VAX C compiler apparently chokes if there is any leading
    whitespace on #if, #ifdef and #end.
    
    The source code claims to be in portable C.
    
    I was not using /STANDARD=PORTABLE when compiling.
    
    Could someone who knows comment on whether #if, #ifdef and #end MUST
    start in column 1?  If not, is there something wrong with the VAX C
    compiler?
================================================================================
Note 553.1         No white space before #if, #ifdef and #end?            1 of 3
EISNER::BURNET "John Burnet"                         10 lines  12-NOV-1992 15:00
     -< '#' must be in col 1, but keyword doesn't have to start in col 2 >-
--------------------------------------------------------------------------------
>    Could someone who knows comment on whether #if, #ifdef and #end MUST
>    start in column 1?  If not, is there something wrong with the VAX C
>    compiler?

The '#' character must be in column 1.  That's specified by the standard,
I believe.  Older preprocessors that are used by compilers on other systems
might recognize preprocessor directives that have white space before the '#',
but that's not kosher and you can't depend on it.

There can be white space between the '#' and the keyword.
================================================================================
Note 553.2         No white space before #if, #ifdef and #end?            2 of 3
EISNER::HUSBY "M. Erik Husby - Lotus Development Co" 19 lines  13-NOV-1992 14:57
                    -< VAX C is not ANSI Standard C (yet)\ >-
--------------------------------------------------------------------------------
>                <<< Note 553.1 by EISNER::BURNET "John Burnet" >>>
>      -< '#' must be in col 1, but keyword doesn't have to start in col 2 >-
> 
> >    Could someone who knows comment on whether #if, #ifdef and #end MUST
> >    start in column 1?  If not, is there something wrong with the VAX C
> >    compiler?
> 
> The '#' character must be in column 1.  That's specified by the standard,
> I believe.  Older preprocessors that are used by compilers on other systems
> might recognize preprocessor directives that have white space before the '#',
> but that's not kosher and you can't depend on it.
> 
> There can be white space between the '#' and the keyword.
> 

	Having just gone through a similar experience, I can state that
	ANSI Standard C allows whitespace between the beginning of the
	line and the '#' character.  VAX C does not.  That is because
	VAX C is not an ANSI Standard C compiler.
================================================================================
Note 553.3         No white space before #if, #ifdef and #end?            3 of 3
EISNER::BURNET "John Burnet"                          7 lines  13-NOV-1992 23:24
                  -< My mistake -- thanks for the correction >-
--------------------------------------------------------------------------------
>  <<< Note 553.2 by EISNER::HUSBY "M. Erik Husby - Lotus Development Corp" >>>
>                    -< VAX C is not ANSI Standard C (yet)\ >-
>
>	Having just gone through a similar experience, I can state that
>	ANSI Standard C allows whitespace between the beginning of the
>	line and the '#' character.  VAX C does not.  That is because
>	VAX C is not an ANSI Standard C compiler.

             <<< EISNER::DUA3:[NOTES$LIBRARY]DEC_SOFTWARE.NOTE;1 >>>
                               -< DEC_SOFTWARE >-
================================================================================
Note 556.0                  Casting NULL on return()?                  3 replies
EISNER::LEDERMAN "Bart Z. Lederman"                  33 lines  20-NOV-1992 17:33
--------------------------------------------------------------------------------

 I've received some good help in other notes on porting a PD BASIC compiler
 obtained from the Internet to VMS.  This appears to be appropriate for
 another topic.  This is a relatively low priority project for me, but I've
 been trying to get a BASIC interpretor for years, and I'm told this one
 runs on UNIX and other platforms and would be useful for people to have. 
 I also think the issues being raised on C code portability will be of
 interest.
    
 There are a number of problems with the code.  For some, I'll have to pull
 out all of the variable's definitions in order to post a question which
 will make sense.

 One problem ought to be easy (for an expert) to fix.

 Many functions are declared as int, and then under certain conditions
 return a NULL, such as the following:

 3740        	int
 3741        	var_make( struct bwb_variable *v, int type )
 3742        	   {

....

 3774    2   	      return NULL;
%CC-I-NONPORTCVT, Conversions between pointers and integers may not be portable.

 I have some idea (I think) why the error occurs, since the header file
 supplied by Digital appears to define NULL as a pointer to zero.  What
 would be a good way to change the return statement so it returns an
 integer value of NULL in a portable way?

================================================================================
Note 556.1                  Casting NULL on return()?                     1 of 3
EISNER::BURNET "John Burnet"                         14 lines  20-NOV-1992 17:52
           -< What type do the calling routines expect to get back? >-
--------------------------------------------------------------------------------
> I have some idea (I think) why the error occurs, since the header file
> supplied by Digital appears to define NULL as a pointer to zero.  What
> would be a good way to change the return statement so it returns an
> integer value of NULL in a portable way?

You're right -- it's the cast to a pointer type that's causing the
compiler to (rightly) flag it as an error.  What you don't want to do
is to change the definition of NULL.  :-)  What you should do depends
on how the functions are used.  For any particular function, if the
value that's returned really is used as a pointer to char, then you
should change the definition and all declarations of that function
so that the type of the result is "char *" rather than int.  If the
value is used as an integer, then you should simply change "return NULL"
to "return 0" as appropriate.
================================================================================
Note 556.2                  Casting NULL on return()?                     2 of 3
EISNER::MAHAN "Patrick Mahan, GAPSIG Moderator"      31 lines  22-NOV-1992 01:06
                     -< Don't cast, return the real thing >-
--------------------------------------------------------------------------------
#             <<< Note 556.0 by EISNER::LEDERMAN "Bart Z. Lederman" >>>
#                          -< Casting NULL on return()? >-
# 
# 
#  One problem ought to be easy (for an expert) to fix.
# 
#  Many functions are declared as int, and then under certain conditions
#  return a NULL, such as the following:
# 
# 
#  3740        	int
#  3741        	var_make( struct bwb_variable *v, int type )
#  3742        	   {
# 
# ....
# 
#  3774    2   	      return NULL;
# %CC-I-NONPORTCVT, Conversions between pointers and integers may not be portable.
# 
#  I have some idea (I think) why the error occurs, since the header file
#  supplied by Digital appears to define NULL as a pointer to zero.  What
#  would be a good way to change the return statement so it returns an
#  integer value of NULL in a portable way?
# 
# 

	Generally, this is not something to worry about.  But if what
	you want is to avoid the error messages, then do the following:

		return 0;
	
================================================================================
Note 556.3                  Casting NULL on return()?                     3 of 3
EISNER::SNYDER_CU "Curt Snyder"                       8 lines  23-NOV-1992 00:50
                           -< casting for responses >-
--------------------------------------------------------------------------------
    Alternately use
    
    return (int) NULL;
    
    which is exactly the same as 
    
    return 0; /* given that all other comments are precise , but this IS
    		the better coding technique */