⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bwb_prn.c

📁 这是一个简易的basic语言解释器, 可供我们学习和改进.
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************	bwb_prn.c       Print and Error-Handling Commands                        for Bywater BASIC Interpreter                        Copyright (c) 1993, Ted A. Campbell                        Bywater Software                        email: tcamp@delphi.com        Copyright and Permissions Information:        All U.S. and international rights are claimed by the author,        Ted A. Campbell.	This software is released under the terms of the GNU General	Public License (GPL), which is distributed with this software	in the file "COPYING".  The GPL specifies the terms under	which users may copy and use the software in this distribution.	A separate license is available for commercial distribution,	for information on which you should contact the author.***************************************************************//*---------------------------------------------------------------*//* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, *//* 11/1995 (eidetics@cerf.net).                                  *//*---------------------------------------------------------------*/#include <stdio.h>#include <ctype.h>#include <math.h>#include "bwbasic.h"#include "bwb_mes.h"/* Prototypes for functions visible only to this file */int prn_col = 1;static int prn_width = 80;	/* default width for stdout */struct prn_fmt   {   int type;			/* STRING, NUMBER, SINGLE, or NUMBER */   int exponential;		/* TRUE = use exponential notation */   int right_justified;		/* TRUE = right justified else left justified */   int width;			/* width of main section */   int precision;		/* width after decimal point */   int commas;                  /* use commas every three steps */   int sign;			/* prefix sign to number */   int money;			/* prefix money sign to number */   int fill;			/* ASCII value for fill character, normally ' ' */   int minus;			/* postfix minus sign to number */   };#if ANSI_Cstatic int prn_cr( char *buffer, FILE *f );static struct prn_fmt *get_prnfmt( char *buffer, int *position, FILE *f );static int bwb_xerror( char *message );static int xxputc( FILE *f, char c );static int xxxputc( FILE *f, char c );static struct bwb_variable * bwb_esetovar( struct exp_ese *e );#elsestatic int prn_cr();static struct prn_fmt *get_prnfmt();static int bwb_xerror();static int xxputc();static int xxxputc();static struct bwb_variable * bwb_esetovar();#endif/***************************************************************        FUNCTION:       bwb_print()        DESCRIPTION:    This function implements the BASIC PRINT                        command.	SYNTAX:		PRINT [# device-number,][USING format-string$;] expressions...***************************************************************/#if ANSI_Cstruct bwb_line *bwb_print( struct bwb_line *l )#elsestruct bwb_line *bwb_print( l )   struct bwb_line *l;#endif   {   FILE *fp;   static int pos;   int req_devnumber;   struct exp_ese *v;   static char *s_buffer;          	/* small, temporary buffer */   static int init = FALSE;#if INTENSIVE_DEBUG   sprintf( bwb_ebuf, "in bwb_print(): enter function" );   bwb_debug( bwb_ebuf );#endif   /* initialize buffers if necessary */   if ( init == FALSE )      {      init = TRUE;      /* Revised to CALLOC pass-thru call by JBV */      if ( ( s_buffer = CALLOC( MAXSTRINGSIZE + 1, sizeof(char), "bwb_print") ) == NULL )         {#if PROG_ERRORS         bwb_error( "in bwb_print(): failed to get memory for s_buffer" );#else         bwb_error( err_getmem );#endif         }      }   /* advance beyond whitespace and check for the '#' sign */   adv_ws( l->buffer, &( l->position ) );#if COMMON_CMDS   if ( l->buffer[ l->position ] == '#' )      {      ++( l->position );      adv_element( l->buffer, &( l->position ), s_buffer );      pos = 0;      v = bwb_exp( s_buffer, FALSE, &pos );      adv_ws( l->buffer, &( l->position ) );      if ( l->buffer[ l->position ] == ',' )         {         ++( l->position );         }      else         {#if PROG_ERRORS	 bwb_error( "in bwb_print(): no comma after #n" );#else         bwb_error( err_syntax );#endif         return bwb_zline( l );         }      req_devnumber = (int) exp_getnval( v );      /* check the requested device number */      if ( ( req_devnumber < 0 ) || ( req_devnumber >= DEF_DEVICES ))         {#if PROG_ERRORS         bwb_error( "in bwb_input(): Requested device number is out of range." );#else         bwb_error( err_devnum );#endif         return bwb_zline( l );         }      if (( dev_table[ req_devnumber ].mode == DEVMODE_CLOSED ) ||         ( dev_table[ req_devnumber ].mode == DEVMODE_AVAILABLE ))         {#if PROG_ERRORS         bwb_error( "in bwb_input(): Requested device number is not open." );#else         bwb_error( err_devnum );#endif         return bwb_zline( l );         }      if ( dev_table[ req_devnumber ].mode != DEVMODE_OUTPUT )         {#if PROG_ERRORS         bwb_error( "in bwb_print(): Requested device is not open for OUTPUT." );#else         bwb_error( err_devnum );#endif         return bwb_zline( l );         }#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_print(): device number is <%d>",         req_devnumber );      bwb_debug( bwb_ebuf );#endif      /* look up the requested device in the device table */      fp = dev_table[ req_devnumber ].cfp;      }   else      {      fp = stdout;      }#else   fp = stdout;#endif				/* COMMON_CMDS */   bwb_xprint( l, fp );   return bwb_zline( l );   }/***************************************************************        FUNCTION:       bwb_xprint()	DESCRIPTION:    This function implements the BASIC PRINT			command, utilizing a specified file our			output device.***************************************************************/#if ANSI_Cintbwb_xprint( struct bwb_line *l, FILE *f )#elseintbwb_xprint( l, f )   struct bwb_line *l;   FILE *f;#endif   {   struct exp_ese *e;   int loop;   static int p;   static int fs_pos;   struct prn_fmt *format;   static char *format_string;   static char *output_string;   static char *element;   static char *prnbuf;   static int init = FALSE;   register int i, j; /* JBV */   int dig_pos, dec_pos; /* JBV */   char tbuf[ MAXSTRINGSIZE + 1 ]; /* JBV */#if INTENSIVE_DEBUG || TEST_BSTRING   bstring *b;#endif   /* initialize buffers if necessary */   if ( init == FALSE )      {      init = TRUE;      /* Revised to CALLOC pass-thru call by JBV */      if ( ( format_string = CALLOC( MAXSTRINGSIZE + 1, sizeof(char), "bwb_xprint") ) == NULL )         {#if PROG_ERRORS         bwb_error( "in bwb_xprint(): failed to get memory for format_string" );#else         bwb_error( err_getmem );#endif         }      /* Revised to CALLOC pass-thru call by JBV */      if ( ( output_string = CALLOC( MAXSTRINGSIZE + 1, sizeof(char), "bwb_xprint") ) == NULL )         {#if PROG_ERRORS         bwb_error( "in bwb_xprint(): failed to get memory for output_string" );#else         bwb_error( err_getmem );#endif         }      /* Revised to CALLOC pass-thru call by JBV */      if ( ( element = CALLOC( MAXSTRINGSIZE + 1, sizeof(char), "bwb_xprint") ) == NULL )         {#if PROG_ERRORS         bwb_error( "in bwb_xprint(): failed to get memory for element buffer" );#else         bwb_error( err_getmem );#endif         }      /* Revised to CALLOC pass-thru call by JBV */      if ( ( prnbuf = CALLOC( MAXSTRINGSIZE + 1, sizeof(char), "bwb_xprint") ) == NULL )         {#if PROG_ERRORS         bwb_error( "in bwb_xprint(): failed to get memory for prnbuf" );#else         bwb_error( err_getmem );#endif         }      }   /* Detect USING Here */   fs_pos = -1;   /* get "USING" in format_string */   p = l->position;   adv_element( l->buffer, &p, format_string );   bwb_strtoupper( format_string );#if COMMON_CMDS   /* check to be sure */   if ( strcmp( format_string, CMD_XUSING ) == 0 )      {      l->position = p;      adv_ws( l->buffer, &( l->position ) );      /* now get the format string in format_string */      e = bwb_exp( l->buffer, FALSE, &( l->position ) );      if ( e->type == STRING )         {         /* copy the format string to buffer */         str_btoc( format_string, exp_getsval( e ) );         /* look for ';' after format string */         fs_pos = 0;         adv_ws( l->buffer, &( l->position ) );         if ( l->buffer[ l->position ] == ';' )            {            ++l->position;            adv_ws( l->buffer, &( l->position ) );            }         else            {#if PROG_ERRORS            bwb_error( "Failed to find \";\" after format string in PRINT USING" );#else            bwb_error( err_syntax );#endif            return FALSE;            }#if INTENSIVE_DEBUG         sprintf( bwb_ebuf, "in bwb_xprint(): Found USING, format string <%s>",            format_string );         bwb_debug( bwb_ebuf );#endif         }      else         {#if PROG_ERRORS         bwb_error( "Failed to find format string after PRINT USING" );#else         bwb_error( err_syntax );#endif         return FALSE;         }      }#endif 			/* COMMON_CMDS */   /* if no arguments, simply print CR and return */   adv_ws( l->buffer, &( l->position ) );   switch( l->buffer[ l->position ] )      {      case '\0':      case '\n':      case '\r':      case ':':         prn_xprintf( f, "\n" );         return TRUE;      default:         break;      }   /* LOOP THROUGH PRINT ELEMENTS */   loop = TRUE;   while( loop == TRUE )      {      /* resolve the string */      e = bwb_exp( l->buffer, FALSE, &( l->position ) );#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_xprint(): op <%d> type <%d>",         e->operation, e->type );      bwb_debug( bwb_ebuf );#endif      /* an OP_NULL probably indicates a terminating ';', but this         will be detected later, so we can ignore it for now */      if ( e->operation != OP_NULL )         {#if TEST_BSTRING         b = exp_getsval( e );         sprintf( bwb_ebuf, "in bwb_xprint(): bstring name is <%s>",            b->name );         bwb_debug( bwb_ebuf );#endif         str_btoc( element, exp_getsval( e ) );         }      else         {         element[ 0 ] = '\0';         }#if INTENSIVE_DEBUG      sprintf( bwb_ebuf, "in bwb_xprint(): element <%s>",         element );      bwb_debug( bwb_ebuf );#endif      /* print with format if there is one */      if (( fs_pos > -1 ) && ( strlen( element ) > 0 ))         {#if COMMON_CMDS         format = get_prnfmt( format_string, &fs_pos, f );#if INTENSIVE_DEBUG	 sprintf( bwb_ebuf, "in bwb_xprint(): format type <%d> width <%d>",            format->type, format->width );         bwb_debug( bwb_ebuf );#endif         switch( format->type )            {            case STRING:               if ( e->type != STRING )                  {#if PROG_ERRORS                  bwb_error( "Type mismatch in PRINT USING" );#else                  bwb_error( err_mismatch );#endif                  }               if ( format->width == -1 ) /* JBV */                  sprintf( output_string, "%s", element );               else sprintf( output_string, "%.*s", format->width, element );#if INTENSIVE_DEBUG               sprintf( bwb_ebuf, "in bwb_xprint(): output string <%s>",                  output_string );               bwb_debug( bwb_ebuf );#endif               prn_xxprintf( f, output_string ); /* Was prn_xprintf (JBV) */               break;	    case NUMBER:               if ( e->type == STRING )                  {#if PROG_ERRORS                  bwb_error( "Type mismatch in PRINT USING" );#else                  bwb_error( err_mismatch );#endif                  }	       if ( format->exponential == TRUE )		  {                  /*------------------------------------------------------*/                  /* NOTE: Width and fill have no effect on C exponential */                  /* format (JBV)                                         */                  /*------------------------------------------------------*/		  if ( format->sign == TRUE ) /* Added by JBV */                     sprintf( output_string, "%+e", exp_getnval( e ) );		  else                     sprintf( output_string, "%e", exp_getnval( e ) );		  }	       else		  {                  /*---------------------------------------------------*/                  /* NOTE: Minus, commas, and money are only valid for */                  /* floating point format (JBV)                       */                  /*---------------------------------------------------*/		  if ( format->sign == TRUE ) /* Added by JBV */		  sprintf( output_string, "%+*.*f",		     format->width, format->precision, exp_getnval( e ) );		  else if ( format->minus == TRUE ) /* Added by JBV */                  {		      sprintf( output_string, "%*.*f",		         format->width, format->precision, exp_getnval( e ) );                      for (i = 0; i < strlen( output_string ); ++i )                      {                          if ( output_string[ i ] != ' ' )                          {                              if ( output_string[ i ] == '-' )                              {                                  output_string[ i ] = ' ';                                  strcat( output_string, "-" );                              }                              else strcat( output_string, " " );                              break;                          }                      }                  }		  else		  sprintf( output_string, "%*.*f",		     format->width, format->precision, exp_getnval( e ) );                  if ( format->commas == TRUE ) /* Added by JBV */                  {                      dig_pos = -1;                      dec_pos = -1;                      for ( i = 0; i < strlen( output_string ); ++i )                      {                          if ( ( isdigit( output_string[ i ] ) != 0 )                          && ( dig_pos == -1 ) )                             dig_pos = i;                          if ( ( output_string[ i ] == '.' )                          && ( dec_pos == -1 ) )                             dec_pos = i;                          if ( ( dig_pos != -1 ) && ( dec_pos != -1 ) ) break;                      }                      if ( dec_pos == -1 ) dec_pos = strlen( output_string );                      j = 0;                      for ( i = 0; i < strlen( output_string ); ++i )                      {                          if ( ( ( dec_pos - i ) % 3 == 0 )                          && ( i > dig_pos ) && ( i < dec_pos ) )                          {                              tbuf[ j ] = ',';                              ++j;                              tbuf[ j ] = '\0';                          }                          tbuf[ j ] = output_string[ i ];                          ++j;                          tbuf[ j ] = '\0';                      }                      strcpy( output_string,                         &tbuf[ strlen( tbuf ) - strlen( output_string ) ] );                  }                  if ( format->money == TRUE ) /* Added by JBV */                  {                      for ( i = 0; i < strlen( output_string ); ++i )                      {                          if ( output_string[ i ] != ' ' )                          {                              if ( i > 0 )                              {                                  if ( isdigit( output_string[ i ] ) == 0 )                                  {                                      output_string[ i - 1 ]                                         = output_string[ i ];                                      output_string[ i ] = '$';                                  }                                  else output_string[ i - 1 ] = '$';                              }                              break;                          }                      }                  }		  }                  if ( format->fill == '*' ) /* Added by JBV */                  for ( i = 0; i < strlen( output_string ); ++i )                  {                     if ( output_string[ i ] != ' ' ) break;                     output_string[ i ] = '*';                  }#if INTENSIVE_DEBUG	       sprintf( bwb_ebuf, "in bwb_xprint(): output number <%f> string <%s>",		  exp_getnval( e ), output_string );	       bwb_debug( bwb_ebuf );#endif               prn_xxprintf( f, output_string ); /* Was prn_xprintf (JBV) */               break;	    default:#if PROG_ERRORS               sprintf( bwb_ebuf, "in bwb_xprint(): get_prnfmt() returns unknown type <%c>",                  format->type );               bwb_error( bwb_ebuf );#else               bwb_error( err_mismatch );#endif               break;            }#endif			/* COMMON_CMDS */         }      /* not a format string: use defaults */      else if ( strlen( element ) > 0 )         {         switch( e->type )            {            case STRING:               prn_xprintf( f, element );               break;            default:#if NUMBER_DOUBLE               sprintf( prnbuf, " %.*lf", prn_precision( bwb_esetovar( e )),                  exp_getnval( e ) );#else               sprintf( prnbuf, " %.*f", prn_precision( bwb_esetovar( e )),                  exp_getnval( e ) );#endif               prn_xprintf( f, prnbuf );               break;            }         }      /* check the position to see if the loop should continue */      adv_ws( l->buffer, &( l->position ) );      switch( l->buffer[ l->position ] )         {#if OLDSTUFF         case ':':		/* end of line segment */	    loop = FALSE;	    break;         case '\0':		/* end of buffer */         case '\n':

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -